Merge "Add VTS for setting layer white point"
diff --git a/atrace/1.0/default/android.hardware.atrace@1.0-service.rc b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
index 7110b45..31459b4 100644
--- a/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
+++ b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
@@ -14,4 +14,4 @@
     interface android.hardware.atrace@1.0::IAtraceDevice default
     class early_hal
     user system
-    group system
+    group system readtracefs
diff --git a/automotive/evs/aidl/Android.bp b/automotive/evs/aidl/Android.bp
new file mode 100644
index 0000000..3c0aa13
--- /dev/null
+++ b/automotive/evs/aidl/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"],
+}
+
+aidl_interface {
+    name: "android.hardware.automotive.evs",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/automotive/evs/*.aidl"
+    ],
+    stability: "vintf",
+    imports: [
+        "android.hardware.common-V2",
+        "android.hardware.graphics.common-V3",
+    ],
+    backend: {
+        java: {
+            // android.hardware.graphics.common package is not enabled
+            // for Java backend.
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+        ndk: {
+            vndk: {
+                enabled: false,
+            },
+            min_sdk_version: "29"
+        },
+    },
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/BufferDesc.aidl
similarity index 84%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/BufferDesc.aidl
index 295fde9..31acdb8 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/BufferDesc.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,13 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable BufferDesc {
+  android.hardware.graphics.common.HardwareBuffer buffer;
+  int pixelSizeBytes;
+  int bufferId;
+  @utf8InCpp String deviceId;
+  long timestamp;
+  byte[] metadata;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraDesc.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraDesc.aidl
index 295fde9..4dadeb8 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraDesc.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable CameraDesc {
+  @utf8InCpp String id;
+  int vendorFlags;
+  byte[] metadata;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraParam.aidl
similarity index 79%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraParam.aidl
index c51aa03..ae4ce77 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/CameraParam.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,20 +31,19 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@Backing(type="byte") @VintfStability
-enum AcquiredInfo {
-  UNKNOWN = 0,
-  GOOD = 1,
-  PARTIAL = 2,
-  INSUFFICIENT = 3,
-  SENSOR_DIRTY = 4,
-  TOO_SLOW = 5,
-  TOO_FAST = 6,
-  VENDOR = 7,
-  START = 8,
-  TOO_DARK = 9,
-  TOO_BRIGHT = 10,
-  IMMOBILE = 11,
-  RETRYING_CAPTURE = 12,
+package android.hardware.automotive.evs;
+@Backing(type="int") @VintfStability
+enum CameraParam {
+  BRIGHTNESS = 0,
+  CONTRAST = 1,
+  AUTOGAIN = 2,
+  GAIN = 3,
+  AUTO_WHITE_BALANCE = 4,
+  WHITE_BALANCE_TEMPERATURE = 5,
+  SHARPNESS = 6,
+  AUTO_EXPOSURE = 7,
+  ABSOLUTE_EXPOSURE = 8,
+  ABSOLUTE_FOCUS = 9,
+  AUTO_FOCUS = 10,
+  ABSOLUTE_ZOOM = 11,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatus.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatus.aidl
index 295fde9..cc066ac 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatus.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable DeviceStatus {
+  @utf8InCpp String id;
+  android.hardware.automotive.evs.DeviceStatusType status;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatusType.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatusType.aidl
index 295fde9..d0f1d8e 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DeviceStatusType.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+package android.hardware.automotive.evs;
+@Backing(type="int") @VintfStability
+enum DeviceStatusType {
+  CAMERA_AVAILABLE = 0,
+  CAMERA_NOT_AVAILABLE = 1,
+  DISPLAY_AVAILABLE = 2,
+  DISPLAY_NOT_AVAILABLE = 3,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayDesc.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayDesc.aidl
index 295fde9..4ac029e 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayDesc.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable DisplayDesc {
+  @utf8InCpp String id;
+  int width;
+  int height;
+  android.hardware.automotive.evs.Rotation orientation;
+  int vendorFlags;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayState.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayState.aidl
index 295fde9..a5f4309 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/DisplayState.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+package android.hardware.automotive.evs;
+@Backing(type="int") @VintfStability
+enum DisplayState {
+  NOT_OPEN = 0,
+  NOT_VISIBLE = 1,
+  VISIBLE_ON_NEXT_FRAME = 2,
+  VISIBLE = 3,
+  DEAD = 4,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventDesc.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventDesc.aidl
index 295fde9..09b2b9d 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventDesc.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable EvsEventDesc {
+  android.hardware.automotive.evs.EvsEventType aType;
+  @utf8InCpp String deviceId;
+  int[] payload;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventType.aidl
similarity index 83%
rename from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl
rename to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventType.aidl
index af7bc3c..052a6b3 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsEventType.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,16 +31,14 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@Backing(type="byte") @VintfStability
-enum Error {
-  UNKNOWN = 0,
-  HW_UNAVAILABLE = 1,
-  UNABLE_TO_PROCESS = 2,
+package android.hardware.automotive.evs;
+@Backing(type="int") @VintfStability
+enum EvsEventType {
+  STREAM_STARTED = 0,
+  STREAM_STOPPED = 1,
+  FRAME_DROPPED = 2,
   TIMEOUT = 3,
-  NO_SPACE = 4,
-  CANCELED = 5,
-  UNABLE_TO_REMOVE = 6,
-  VENDOR = 7,
-  BAD_CALIBRATION = 8,
+  PARAMETER_CHANGED = 4,
+  MASTER_RELEASED = 5,
+  STREAM_ERROR = 6,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsResult.aidl
similarity index 79%
rename from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
rename to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsResult.aidl
index c51aa03..a0418a9 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/EvsResult.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,20 +31,18 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@Backing(type="byte") @VintfStability
-enum AcquiredInfo {
-  UNKNOWN = 0,
-  GOOD = 1,
-  PARTIAL = 2,
-  INSUFFICIENT = 3,
-  SENSOR_DIRTY = 4,
-  TOO_SLOW = 5,
-  TOO_FAST = 6,
-  VENDOR = 7,
-  START = 8,
-  TOO_DARK = 9,
-  TOO_BRIGHT = 10,
-  IMMOBILE = 11,
-  RETRYING_CAPTURE = 12,
+package android.hardware.automotive.evs;
+@Backing(type="int") @VintfStability
+enum EvsResult {
+  OK = 0,
+  INVALID_ARG = 1,
+  STREAM_ALREADY_RUNNING = 2,
+  BUFFER_NOT_AVAILABLE = 3,
+  OWNERSHIP_LOST = 4,
+  UNDERLYING_SERVICE_ERROR = 5,
+  PERMISSION_DENIED = 6,
+  RESOURCE_NOT_AVAILABLE = 7,
+  RESOURCE_BUSY = 8,
+  NOT_IMPLEMENTED = 9,
+  NOT_SUPPORTED = 10,
 }
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCamera.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCamera.aidl
new file mode 100644
index 0000000..ce1b97d
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCamera.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.evs;
+@VintfStability
+interface IEvsCamera {
+  void doneWithFrame(in android.hardware.automotive.evs.BufferDesc[] buffer);
+  void forcePrimaryClient(in android.hardware.automotive.evs.IEvsDisplay display);
+  android.hardware.automotive.evs.CameraDesc getCameraInfo();
+  byte[] getExtendedInfo(in int opaqueIdentifier);
+  int[] getIntParameter(in android.hardware.automotive.evs.CameraParam id);
+  android.hardware.automotive.evs.ParameterRange getIntParameterRange(in android.hardware.automotive.evs.CameraParam id);
+  android.hardware.automotive.evs.CameraParam[] getParameterList();
+  android.hardware.automotive.evs.CameraDesc getPhysicalCameraInfo(in String deviceId);
+  int importExternalBuffers(in android.hardware.automotive.evs.BufferDesc[] buffers);
+  void pauseVideoStream();
+  void resumeVideoStream();
+  void setExtendedInfo(in int opaqueIdentifier, in byte[] opaqueValue);
+  int[] setIntParameter(in android.hardware.automotive.evs.CameraParam id, in int value);
+  void setPrimaryClient();
+  void setMaxFramesInFlight(in int bufferCount);
+  void startVideoStream(in android.hardware.automotive.evs.IEvsCameraStream receiver);
+  void stopVideoStream();
+  void unsetPrimaryClient();
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCameraStream.aidl
similarity index 84%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCameraStream.aidl
index 295fde9..6e2e64a 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsCameraStream.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+interface IEvsCameraStream {
+  oneway void deliverFrame(in android.hardware.automotive.evs.BufferDesc[] buffer);
+  oneway void notify(in android.hardware.automotive.evs.EvsEventDesc event);
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsDisplay.aidl
similarity index 76%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsDisplay.aidl
index c51aa03..9b538d4 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsDisplay.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,20 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@Backing(type="byte") @VintfStability
-enum AcquiredInfo {
-  UNKNOWN = 0,
-  GOOD = 1,
-  PARTIAL = 2,
-  INSUFFICIENT = 3,
-  SENSOR_DIRTY = 4,
-  TOO_SLOW = 5,
-  TOO_FAST = 6,
-  VENDOR = 7,
-  START = 8,
-  TOO_DARK = 9,
-  TOO_BRIGHT = 10,
-  IMMOBILE = 11,
-  RETRYING_CAPTURE = 12,
+package android.hardware.automotive.evs;
+@VintfStability
+interface IEvsDisplay {
+  android.hardware.automotive.evs.DisplayDesc getDisplayInfo();
+  android.hardware.automotive.evs.DisplayState getDisplayState();
+  android.hardware.automotive.evs.BufferDesc getTargetBuffer();
+  void returnTargetBufferForDisplay(in android.hardware.automotive.evs.BufferDesc buffer);
+  void setDisplayState(in android.hardware.automotive.evs.DisplayState state);
 }
diff --git a/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumerator.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumerator.aidl
new file mode 100644
index 0000000..a79c68d
--- /dev/null
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumerator.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.automotive.evs;
+@VintfStability
+interface IEvsEnumerator {
+  void closeCamera(in android.hardware.automotive.evs.IEvsCamera carCamera);
+  void closeDisplay(in android.hardware.automotive.evs.IEvsDisplay display);
+  void closeUltrasonicsArray(in android.hardware.automotive.evs.IEvsUltrasonicsArray evsUltrasonicsArray);
+  android.hardware.automotive.evs.CameraDesc[] getCameraList();
+  byte[] getDisplayIdList();
+  android.hardware.automotive.evs.DisplayState getDisplayState();
+  android.hardware.automotive.evs.Stream[] getStreamList(in android.hardware.automotive.evs.CameraDesc description);
+  android.hardware.automotive.evs.UltrasonicsArrayDesc[] getUltrasonicsArrayList();
+  boolean isHardware();
+  android.hardware.automotive.evs.IEvsCamera openCamera(in String cameraId, in android.hardware.automotive.evs.Stream streamCfg);
+  android.hardware.automotive.evs.IEvsDisplay openDisplay(in byte id);
+  android.hardware.automotive.evs.IEvsUltrasonicsArray openUltrasonicsArray(in String ultrasonicsArrayId);
+  void registerStatusCallback(in android.hardware.automotive.evs.IEvsEnumeratorStatusCallback callback);
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl
index 295fde9..c39a4e8 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+interface IEvsEnumeratorStatusCallback {
+  oneway void deviceStatusChanged(in android.hardware.automotive.evs.DeviceStatus[] status);
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl
similarity index 77%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl
index 295fde9..1183ab3 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+interface IEvsUltrasonicsArray {
+  void doneWithDataFrame(in android.hardware.automotive.evs.UltrasonicsDataFrameDesc dataFrameDesc);
+  android.hardware.automotive.evs.UltrasonicsArrayDesc getUltrasonicArrayInfo();
+  void setMaxFramesInFlight(in int bufferCount);
+  void startStream(in android.hardware.automotive.evs.IEvsUltrasonicsArrayStream stream);
+  void stopStream();
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl
similarity index 83%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl
index 295fde9..510b0a4 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+interface IEvsUltrasonicsArrayStream {
+  oneway void deliverDataFrame(in android.hardware.automotive.evs.UltrasonicsDataFrameDesc dataFrameDesc);
+  oneway void notify(in android.hardware.automotive.evs.EvsEventDesc event);
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/ParameterRange.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/ParameterRange.aidl
index 295fde9..44e9b59 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/ParameterRange.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable ParameterRange {
+  int min;
+  int max;
+  int step;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Rotation.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Rotation.aidl
index 295fde9..91971fc 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Rotation.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+package android.hardware.automotive.evs;
+@Backing(type="int") @VintfStability
+enum Rotation {
+  ROTATION_0 = 0,
+  ROTATION_90 = 1,
+  ROTATION_180 = 2,
+  ROTATION_270 = 3,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/RotationQuaternion.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/RotationQuaternion.aidl
index 295fde9..d9c8b6e 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/RotationQuaternion.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable RotationQuaternion {
+  float x;
+  float y;
+  float z;
+  float w;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/SensorPose.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/SensorPose.aidl
index 295fde9..4ead9ea 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/SensorPose.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable SensorPose {
+  android.hardware.automotive.evs.RotationQuaternion rotation;
+  android.hardware.automotive.evs.Translation translation;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Stream.aidl
similarity index 81%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Stream.aidl
index 295fde9..a780412 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Stream.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,14 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable Stream {
+  int id;
+  android.hardware.automotive.evs.StreamType streamType;
+  int width;
+  int height;
+  android.hardware.graphics.common.PixelFormat format;
+  android.hardware.graphics.common.BufferUsage usage;
+  android.hardware.automotive.evs.Rotation rotation;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/StreamType.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/StreamType.aidl
index 295fde9..9819c89 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/StreamType.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+package android.hardware.automotive.evs;
+@Backing(type="int") @VintfStability
+enum StreamType {
+  OUTPUT = 0,
+  INPUT = 1,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Translation.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Translation.aidl
index 295fde9..488d80f 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/Translation.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable Translation {
+  float x;
+  float y;
+  float z;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicSensor.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicSensor.aidl
index 295fde9..23f81f8 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicSensor.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable UltrasonicSensor {
+  android.hardware.automotive.evs.SensorPose pose;
+  float maxRangeMm;
+  float angleOfMeasurement;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl
similarity index 84%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl
index 295fde9..4a98875 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable UltrasonicsArrayDesc {
+  @utf8InCpp String ultrasonicsArrayId;
+  int maxReadingsPerSensorCount;
+  int maxReceiversCount;
+  android.hardware.automotive.evs.UltrasonicSensor[] sensors;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl
similarity index 83%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl
index 295fde9..35ec84b 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/automotive/evs/aidl/aidl_api/android.hardware.automotive.evs/current/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,13 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.automotive.evs;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable UltrasonicsDataFrameDesc {
+  long timestampNs;
+  int id;
+  byte[] transmittersIdList;
+  byte[] receiversIdList;
+  int[] receiversReadingsCountList;
+  android.hardware.common.Ashmem waveformsData;
 }
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/BufferDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/BufferDesc.aidl
new file mode 100644
index 0000000..0604abe
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/BufferDesc.aidl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.graphics.common.HardwareBuffer;
+
+/**
+ * Structure representing an image buffer through our APIs
+ *
+ * In addition to the handle to the graphics memory, we need to retain
+ * the properties of the buffer for easy reference and reconstruction of
+ * an ANativeWindowBuffer object on the remote side of API calls.
+ * (Not least because OpenGL expect an ANativeWindowBuffer* for us as a
+ * texture via eglCreateImageKHR()).
+ */
+@VintfStability
+parcelable BufferDesc {
+    /**
+     * Stable AIDL counter part of AHardwareBuffer.  Please see
+     * hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/HardwareBuffer.aidl
+     * for more details.
+     */
+    HardwareBuffer buffer;
+    /**
+     * The size of a pixel in the units of bytes.
+     */
+    int pixelSizeBytes;
+    /**
+     * Opaque value from driver
+     */
+    int bufferId;
+    /**
+     * Unique identifier of the physical camera device that produces this buffer.
+     */
+    @utf8InCpp
+    String deviceId;
+    /**
+     * Time that this buffer is being filled in the units of microseconds and must be
+     * obtained from android::elapsedRealtimeNanos() or its equivalents.
+     */
+    long timestamp;
+    /**
+     * Frame metadata.  This is opaque to EvsManager.
+     */
+    byte[] metadata;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/CameraDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/CameraDesc.aidl
new file mode 100644
index 0000000..2f500a7
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/CameraDesc.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.automotive.evs;
+
+/**
+ * Structure describing the basic properties of an EVS camera.
+ *
+ * The HAL is responsible for filling out this structure for each
+ * EVS camera in the system.
+ */
+@VintfStability
+parcelable CameraDesc {
+    /**
+     * Unique identifier for camera devices.  This may be a path to detected
+     * camera device; for example, "/dev/video0".
+     */
+    @utf8InCpp
+    String id;
+    /**
+     * Opaque value from driver.  Vendor may use this field to store additional
+     * information; for example, sensor and bridge chip id.
+     */
+    int vendorFlags;
+    /**
+     * Store camera metadata such as lens characteristics.
+     */
+    byte[] metadata;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/CameraParam.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/CameraParam.aidl
new file mode 100644
index 0000000..15500b2
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/CameraParam.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+/**
+ * EVS camera parameter
+ */
+@VintfStability
+@Backing(type="int")
+enum CameraParam {
+    /**
+     * The brightness of image frames
+     */
+    BRIGHTNESS,
+    /**
+     * The contrast of image frames
+     */
+    CONTRAST,
+    /**
+     * Automatic gain/exposure control
+     */
+    AUTOGAIN,
+    /**
+     * Gain control
+     */
+    GAIN,
+    /**
+     * Automatic Whitebalance
+     */
+    AUTO_WHITE_BALANCE,
+    /**
+     * Manual white balance setting as a color temperature in Kelvin.
+     */
+    WHITE_BALANCE_TEMPERATURE,
+    /**
+     * Image sharpness adjustment
+     */
+    SHARPNESS,
+    /**
+     * Auto Exposure Control modes; auto, manual, shutter priority, or
+     * aperture priority.
+     */
+    AUTO_EXPOSURE,
+    /**
+     * Manual exposure time of the camera
+     */
+    ABSOLUTE_EXPOSURE,
+    /**
+     * Sets the focal point of the camera to the specified position.  This
+     * parameter may not be effective when auto focus is enabled.
+     */
+    ABSOLUTE_FOCUS,
+    /**
+     * Enables continuous automatic focus adjustments.
+     */
+    AUTO_FOCUS,
+    /**
+     * Specifies the objective lens focal length as an absolute value.
+     */
+    ABSOLUTE_ZOOM,
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatus.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatus.aidl
new file mode 100644
index 0000000..535ace3
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatus.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.DeviceStatusType;
+
+/**
+ * The status of the devices, as sent by EVS HAL through the
+ * IEvsEnumeratorCallback::deviceStatusChanged() call.
+ */
+@VintfStability
+parcelable DeviceStatus {
+    /**
+     * The identifier of a device that has transitioned to a new status.
+     */
+    @utf8InCpp
+    String id;
+    /**
+     * A new status of this device
+     */
+    DeviceStatusType status;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatusType.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatusType.aidl
new file mode 100644
index 0000000..902b31b
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/DeviceStatusType.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.automotive.evs;
+
+/**
+ * The status of the devices available through the EVS
+ */
+@VintfStability
+@Backing(type="int")
+enum DeviceStatusType {
+    /**
+     * A camera device is available and ready to be used.
+     */
+    CAMERA_AVAILABLE,
+    /**
+     * A camera device is not available; e.g. disconnected from the system.
+     */
+    CAMERA_NOT_AVAILABLE,
+    /**
+     * A display device is available and ready to be used.
+     */
+    DISPLAY_AVAILABLE,
+    /**
+     * A display device is not available; e.g. disconnected from the
+     * system.
+     */
+    DISPLAY_NOT_AVAILABLE,
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/DisplayDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/DisplayDesc.aidl
new file mode 100644
index 0000000..0b4243b
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/DisplayDesc.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.Rotation;
+
+/**
+ * Structure describing the basic properties of an EVS display
+ *
+ * The HAL is responsible for filling out this structure to describe
+ * the EVS display. As an implementation detail, this may be a physical
+ * display or a virtual display that is overlaid or mixed with another
+ * presentation device.
+ */
+@VintfStability
+parcelable DisplayDesc {
+    /**
+     * Unique identifier for the display
+     */
+    @utf8InCpp
+    String id;
+    /**
+     * The width of the display
+     */
+    int width;
+    /**
+     * The height of the display
+     */
+    int height;
+    /**
+     * Counterclock-wise orientation of the display
+     */
+    Rotation orientation;
+    /**
+     * Opaque value from driver.  Vendor may use this field to store additional
+     * information; for example, sensor and bridge chip id.
+     */
+    int vendorFlags;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/DisplayState.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/DisplayState.aidl
new file mode 100644
index 0000000..c242d2f
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/DisplayState.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+/**
+ * States for control of the EVS display
+ *
+ * The DisplayInfo structure describes the basic properties of an EVS display. Any EVS
+ * implementation is required to have one. The HAL is responsible for filling out this
+ * structure to describe the EVS display. As an implementation detail, this may be a
+ * physical display or a virtual display that is overlaid or mixed with another
+ * presentation device.
+ */
+@VintfStability
+@Backing(type="int")
+enum DisplayState {
+    /*
+     * Display has not been requested by any application yet
+     */
+    NOT_OPEN = 0,
+    /*
+     * Display is inhibited
+     */
+    NOT_VISIBLE,
+    /*
+     * Will become visible with next frame
+     */
+    VISIBLE_ON_NEXT_FRAME,
+    /*
+     * Display is currently active
+     */
+    VISIBLE,
+    /*
+     * Driver is in an undefined state.  Interface should be closed.
+     */
+    DEAD,
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventDesc.aidl
new file mode 100644
index 0000000..ebff98f
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventDesc.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.EvsEventType;
+
+/**
+ * Structure that describes informative events occurred during EVS is streaming
+ */
+@VintfStability
+parcelable EvsEventDesc {
+    /**
+     * Type of an informative event
+     */
+    EvsEventType aType;
+    /**
+     * Device identifier
+     */
+    @utf8InCpp
+    String deviceId;
+    /**
+     * Possible additional vendor information that is opaque to the EvsManager
+     */
+    int[] payload;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventType.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventType.aidl
new file mode 100644
index 0000000..3a493af
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventType.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+/**
+ * Types of informative streaming events
+ */
+@VintfStability
+@Backing(type="int")
+enum EvsEventType {
+    /**
+     * Video stream is started
+     */
+    STREAM_STARTED = 0,
+    /**
+     * Video stream is stopped
+     */
+    STREAM_STOPPED,
+    /**
+     * Video frame is dropped
+     */
+    FRAME_DROPPED,
+    /**
+     * Timeout happens
+     */
+    TIMEOUT,
+    /**
+     * Camera parameter is changed; payload contains a changed parameter ID and
+     * its value
+     */
+    PARAMETER_CHANGED,
+    /**
+     * Master role has become available
+     */
+    MASTER_RELEASED,
+    /**
+     * Any other erroneous streaming events
+     */
+    STREAM_ERROR,
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/EvsResult.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/EvsResult.aidl
new file mode 100644
index 0000000..c355be3
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/EvsResult.aidl
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+/**
+ * Error codes used in EVS HAL interface.
+ */
+@VintfStability
+@Backing(type="int")
+enum EvsResult {
+    OK = 0,
+    /**
+     * Given arguments are invalid
+     */
+    INVALID_ARG,
+    /**
+     * Requested stream is already running
+     */
+    STREAM_ALREADY_RUNNING,
+    /**
+     * Buffer is not available; e.g. failed to allocate
+     */
+    BUFFER_NOT_AVAILABLE,
+    /**
+     * Ownership has been expired or stolen by other clients
+     */
+    OWNERSHIP_LOST,
+    /**
+     * A dependent service fails to handle a request
+     */
+    UNDERLYING_SERVICE_ERROR,
+    /**
+     * Permission denied
+     */
+    PERMISSION_DENIED,
+    /**
+     * Either the camera or the display is not available
+     */
+    RESOURCE_NOT_AVAILABLE,
+    /**
+     * Device or resource busy
+     */
+    RESOURCE_BUSY,
+    /**
+     * A method is not implemented yet
+     */
+    NOT_IMPLEMENTED,
+    /**
+     * Requested functionality is not supported
+     */
+    NOT_SUPPORTED,
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCamera.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCamera.aidl
new file mode 100644
index 0000000..080dd75
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCamera.aidl
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.evs;
+
+import android.hardware.automotive.evs.BufferDesc;
+import android.hardware.automotive.evs.CameraDesc;
+import android.hardware.automotive.evs.CameraParam;
+import android.hardware.automotive.evs.IEvsCameraStream;
+import android.hardware.automotive.evs.IEvsDisplay;
+import android.hardware.automotive.evs.ParameterRange;
+
+/**
+ * Represents a single camera and is the primary interface for capturing images.
+ */
+@VintfStability
+interface IEvsCamera {
+    /**
+     * Returns frames that were delivered to the IEvsCameraStream.
+     *
+     * When done consuming a frame delivered to the IEvsCameraStream
+     * interface, it must be returned to the IEvsCamera for reuse.
+     * A small, finite number of buffers are available (possibly as small
+     * as one), and if the supply is exhausted, no further frames may be
+     * delivered until a buffer is returned.
+     *
+     * @param in buffer Buffers to be returned.
+     */
+    void doneWithFrame(in BufferDesc[] buffer);
+
+    /**
+     * Sets to be the primary client forcibly.
+     *
+     * The client, which owns the display, has a high priority and can take over
+     * a primary client role from other clients without the display.
+     *
+     * @param in display IEvsDisplay handle.  If a given display is in either
+     *                   NOT_VISIBLE, VISIBLE_ON_NEXT_FRAME, or VISIBLE state, the
+     *                   calling client is considered as the high priority client
+     *                   and therefore allowed to take over a primary client role from
+     *                   existing primary client.
+     * @throws EvsResult::INVALID_ARG if a given display handle is null or invalid states.
+     */
+    void forcePrimaryClient(in IEvsDisplay display);
+
+    /**
+     * Returns the description of this camera.
+     *
+     * @return The description of this camera.  This must be the same value as
+     *         reported by IEvsEnumerator::getCameraList().
+     */
+    CameraDesc getCameraInfo();
+
+    /**
+     * Request driver specific information from the HAL implementation.
+     *
+     * The values allowed for opaqueIdentifier are driver specific,
+     * but no value passed in may crash the driver.
+     *
+     * @param in opaqueIdentifier An unique identifier of the information to
+     *                            request.
+     * @return Requested information.  Zero-size vector is returned if the driver does
+     *         not recognize a given identifier.
+     * @throws EvsResult::INVALID_ARG for any unrecognized opaqueIdentifier.
+     */
+    byte[] getExtendedInfo(in int opaqueIdentifier);
+
+    /**
+     * Retrieves values of given camera parameter.  The driver must report
+     * EvsResult::INVALID_ARG if a request parameter is not supported.
+     *
+     * @param in id The identifier of camera parameter, CameraParam enum.
+     * @return Values of requested camera parameter, the same number of values as
+     *         backing camera devices.
+     * @throws EvsResult::INVALID_ARG for any unrecognized parameter.
+     *        EvsResult::UNDERLYING_SERVICE_ERROR for any other failures.
+     */
+    int[] getIntParameter(in CameraParam id);
+
+    /**
+     * Requests a valid value range of a camera parameter
+     *
+     * @param in id The identifier of camera parameter, CameraParam enum.
+     * @return ParameterRange of a requested CameraParam
+     */
+    ParameterRange getIntParameterRange(in CameraParam id);
+
+    /**
+     * Retrieves a list of parameters this camera supports.
+     *
+     * @return A list of CameraParam that this camera supports.
+     */
+    CameraParam[] getParameterList();
+
+    /**
+     * Returns the description of the physical camera device that backs this
+     * logical camera.
+     *
+     * If a requested device does not either exist or back this logical device,
+     * this method returns a null camera descriptor.  And, if this is called on
+     * a physical camera device, this method is the same as getCameraInfo()
+     * method if a given device ID is matched.  Otherwise, this will return a
+     * null camera descriptor.
+     *
+     * @param in deviceId Physical camera device identifier string.
+     * @return The description of a member physical camera device.
+     *         This must be the same value as reported by IEvsEnumerator::getCameraList().
+     */
+    CameraDesc getPhysicalCameraInfo(in String deviceId);
+
+    /**
+     * Import external buffers to capture frames
+     *
+     * This API must be called with a physical camera device identifier.
+     *
+     * @param in buffers A list of buffers allocated by the caller.  EvsCamera
+     *                   will use these buffers to capture frames, in addition to
+     *                   other buffers already in its buffer pool.
+     * @return The amount of buffer pool size changes after importing given buffers.
+     */
+    int importExternalBuffers(in BufferDesc[] buffers);
+
+    /**
+     * Requests to pause EVS camera stream events.
+     *
+     * Like stopVideoStream(), events may continue to arrive for some time
+     * after this call returns. Delivered frame buffers must be returned.
+     */
+    void pauseVideoStream();
+
+    /**
+     * Requests to resume EVS camera stream.
+     */
+    void resumeVideoStream();
+
+    /**
+     * Send a driver specific value to the HAL implementation.
+     *
+     * This extension is provided to facilitate car specific
+     * extensions, but no HAL implementation may require this call
+     * in order to function in a default state.
+     * INVALID_ARG is returned if the opaqueValue is not meaningful to
+     * the driver implementation.
+     *
+     * @param in opaqueIdentifier An unique identifier of the information to
+     *                            program.
+     *        in opaqueValue A value to program.
+     * @throws EvsResult::INVALID_ARG if this call fails to set a parameter.
+     */
+    void setExtendedInfo(in int opaqueIdentifier, in byte[] opaqueValue);
+
+    /**
+     * Requests to set a camera parameter.
+     *
+     * Only a request from the primary client will be processed successfully.
+     * When this method is called on a logical camera device, it will be forwarded
+     * to each physical device and, if it fails to program any physical device,
+     * it will return an error code with the same number of effective values as
+     * the number of backing camera devices.
+     *
+     * @param in id The identifier of camera parameter, CameraParam enum.
+     * @param in value A desired parameter value.
+     * @return Programmed parameter values.  This may differ from what the client
+     *         gives if, for example, the driver does not support a target parameter.
+     * @throws EvsResult::INVALID_ARG if either the request is not made by the primary
+     *        client, or a requested parameter is not supported.
+     *        EvsResult::UNDERLYING_SERVICE_ERROR if it fails to program a value by any
+     *        other reason.
+     */
+    int[] setIntParameter(in CameraParam id, in int value);
+
+    /**
+     * Requests to be the primary client.
+     *
+     * When multiple clients subscribe to a single camera hardware and one of
+     * them adjusts a camera parameter such as the contrast, it may disturb
+     * other clients' operations.  Therefore, the client must call this method
+     * to be a primary client.  Once it becomes a primary client, it will be able to
+     * change camera parameters until either it dies or explicitly gives up the
+     * role.
+     *
+     * @throws EvsResult::OWNERSHIP_LOST if there is already the primary client.
+     */
+    void setPrimaryClient();
+
+    /**
+     * Specifies the depth of the buffer chain the camera is asked to support.
+     *
+     * Up to this many frames may be held concurrently by the client of IEvsCamera.
+     * If this many frames have been delivered to the receiver without being returned
+     * by doneWithFrame, the stream must skip frames until a buffer is returned for reuse.
+     * It is legal for this call to come at any time, even while streams are already running,
+     * in which case buffers should be added or removed from the chain as appropriate.
+     * If no call is made to this entry point, the IEvsCamera must support at least one
+     * frame by default. More is acceptable.
+     *
+     * @param in bufferCount Number of buffers the client of IEvsCamera may hold concurrently.
+     * @throws EvsResult::BUFFER_NOT_AVAILABLE if the client cannot increase the max frames.
+     *        EvsResult::INVALID_ARG if the client cannot decrease the max frames.
+     *        EvsResult::OWNERSHIP_LOST if we lost an ownership of a target camera.
+     */
+    void setMaxFramesInFlight(in int bufferCount);
+
+    /**
+     * Request to start EVS camera stream from this camera.
+     *
+     * The IEvsCameraStream must begin receiving calls with various events
+     * including new image frame ready until stopVideoStream() is called.
+     *
+     * @param in receiver IEvsCameraStream implementation.
+     * @throws EvsResult::OWNERSHIP_LOST if we lost an ownership of a target camera.
+     *        EvsResult::STREAM_ALREADY_RUNNING if a video stream has been started already.
+     *        EvsResult::BUFFER_NOT_AVAILABLE if it fails to secure a minimum number of
+     *        buffers to run a video stream.
+     *        EvsResult::UNDERLYING_SERVICE_ERROR for all other failures.
+     */
+    void startVideoStream(in IEvsCameraStream receiver);
+
+    /**
+     * Stop the delivery of EVS camera frames.
+     *
+     * Because delivery is asynchronous, frames may continue to arrive for
+     * some time after this call returns. Each must be returned until the
+     * closure of the stream is signaled to the IEvsCameraStream.
+     * This function cannot fail and is simply ignored if the stream isn't running.
+     */
+    void stopVideoStream();
+
+    /**
+     * Retires from the primary client role.
+     *
+     * @throws EvsResult::INVALID_ARG if the caller client is not a primary client.
+     */
+    void unsetPrimaryClient();
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCameraStream.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCameraStream.aidl
new file mode 100644
index 0000000..2c2b44c
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCameraStream.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.BufferDesc;
+import android.hardware.automotive.evs.EvsEventDesc;
+import android.hardware.graphics.common.HardwareBuffer;
+
+/**
+ * Implemented on client side to receive asynchronous streaming event deliveries.
+ */
+@VintfStability
+oneway interface IEvsCameraStream {
+    /**
+     * Receives calls from the HAL each time video frames is ready for inspection.
+     * Buffer handles received by this method must be returned via calls to
+     * IEvsCamera::doneWithFrame(). When the video stream is stopped via a call
+     * to IEvsCamera::stopVideoStream(), this callback may continue to happen for
+     * some time as the pipeline drains. Each frame must still be returned.
+     * When the last frame in the stream has been delivered, STREAM_STOPPED
+     * event must be delivered.  No further frame deliveries may happen
+     * thereafter.
+     *
+     * A camera device will deliver the same number of frames as number of
+     * backing physical camera devices; it means, a physical camera device
+     * sends always a single frame and a logical camera device sends multiple
+     * frames as many as number of backing physical camera devices.
+     *
+     * @param in buffer Buffer descriptors of delivered image frames.
+     */
+    void deliverFrame(in BufferDesc[] buffer);
+
+    /**
+     * Receives calls from the HAL each time an event happens.
+     *
+     * @param in event EVS event with possible event information.
+     */
+    void notify(in EvsEventDesc event);
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsDisplay.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsDisplay.aidl
new file mode 100644
index 0000000..8d57014
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsDisplay.aidl
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.BufferDesc;
+import android.hardware.automotive.evs.DisplayDesc;
+import android.hardware.automotive.evs.DisplayState;
+
+/**
+ * Represents a single display.
+ */
+@VintfStability
+interface IEvsDisplay {
+    /**
+     * Returns the description of this display.
+     *
+     * @return The information of this display including id, current mode, current state,
+     *         and additional vendor-specific information.
+     * @throws EvsResult::UNDERLYING_SERVICE_ERROR if it fails to read a display information.
+     */
+    DisplayDesc getDisplayInfo();
+
+    /**
+     * This call requests the current state of the display
+     *
+     * The HAL implementation should report the actual current state, which might
+     * transiently differ from the most recently requested state. Note, however, that
+     * the logic responsible for changing display states should generally live above
+     * the device layer, making it undesirable for the HAL implementation to spontaneously
+     * change display states.
+     *
+     * @return Current DisplayState of this Display.
+     */
+    DisplayState getDisplayState();
+
+    /**
+     * This call returns a handle to a frame buffer associated with the display.
+     *
+     * @return A handle to a frame buffer.  The returned buffer may be locked and
+     *         written to by software and/or GL.  This buffer must be returned via
+     *         a call to returnTargetBufferForDisplay() even if the display is no
+     *         longer visible.
+     * @throws EvsResult::OWNERSHIP_LOST if a display is in DisplayState::DEAD.
+     *        EvsResult::BUFFER_NOT_AVAILABLE if no buffer is available.
+     *        EvsResult::UNDERLYING_SERVICE_ERROR for any other failures.
+     */
+    BufferDesc getTargetBuffer();
+
+    /**
+     * This call tells the display that the buffer is ready for display.
+     *
+     * The buffer is no longer valid for use by the client after this call.
+     * There is no maximum time the caller may hold onto the buffer before making this
+     * call. The buffer may be returned at any time and in any DisplayState, but all
+     * buffers are expected to be returned before the IEvsDisplay interface is destroyed.
+     *
+     * @param in buffer A buffer handle to the frame that is ready for display.
+     * @throws EvsResult::INVALID_ARG if a given buffer is unknown or invalid.
+     *        EvsResult::OWNERSHIP_LOST if a display is in DisplayState::DEAD.
+     *        EvsResult::UNDERLYING_SERVICE_ERROR for any other failures.
+     */
+    void returnTargetBufferForDisplay(in BufferDesc buffer);
+
+    /**
+     * Clients may set the display state to express their desired state.
+     *
+     * The HAL implementation must gracefully accept a request for any state while in
+     * any other state, although the response may be to defer or ignore the request. The display
+     * is defined to start in the NOT_VISIBLE state upon initialization. The client is
+     * then expected to request the VISIBLE_ON_NEXT_FRAME state, and then begin providing
+     * video. When the display is no longer required, the client is expected to request
+     * the NOT_VISIBLE state after passing the last video frame.
+     * Returns INVALID_ARG if the requested state is not a recognized value.
+     *
+     * @param in state Desired new DisplayState.
+     * @throws EvsResult::INVALID_ARG if a given state is invalid.
+     *        EvsResult::OWNERSHIP_LOST if a display is in DisplayState::DEAD.
+     */
+    void setDisplayState(in DisplayState state);
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumerator.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumerator.aidl
new file mode 100644
index 0000000..8e380e0
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumerator.aidl
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.CameraDesc;
+import android.hardware.automotive.evs.DisplayState;
+import android.hardware.automotive.evs.IEvsCamera;
+import android.hardware.automotive.evs.IEvsDisplay;
+import android.hardware.automotive.evs.IEvsEnumeratorStatusCallback;
+import android.hardware.automotive.evs.IEvsUltrasonicsArray;
+import android.hardware.automotive.evs.Stream;
+import android.hardware.automotive.evs.UltrasonicsArrayDesc;
+
+/**
+ * Provides the mechanism for EVS camera and ultrasonics array discovery
+ */
+@VintfStability
+interface IEvsEnumerator {
+    /**
+     * Return the specified IEvsCamera interface as no longer in use
+     *
+     * When the IEvsCamera object is no longer required, it must be released.
+     * NOTE: Video streaming must be cleanly stopped before making this call.
+     *
+     * @param in carCamera EvsCamera object to be closed.
+     * @throws EvsResult::INVALID_ARG if a given camera object is invalid.
+     */
+    void closeCamera(in IEvsCamera carCamera);
+
+    /**
+     * Return the specified IEvsDisplay interface as no longer in use
+     *
+     * When the IEvsDisplay object is no longer required, it must be released.
+     * NOTE: All buffers must have been returned to the display before making this call.
+     *
+     * @param in display EvsDisplay object to be closed.
+     */
+    void closeDisplay(in IEvsDisplay display);
+
+    /**
+     * Return the specified IEvsUltrasonicsArray interface as no longer in use
+     *
+     * When the IEvsUltrasonicsArray object is no longer required, it must be released.
+     * NOTE: Data streaming must be cleanly stopped before making this call.
+     *
+     * @param in evsUltrasonicsArray EvsUltrasonics array object to be closed.
+     */
+    void closeUltrasonicsArray(in IEvsUltrasonicsArray evsUltrasonicsArray);
+
+    /**
+     * Returns a list of all EVS cameras available to the system
+     *
+     * @return A list of cameras availale for EVS service.
+     * @throws EvsResult::PERMISSION_DENIED if the process is not permitted to enumerate
+     *        camera devices.
+     */
+    CameraDesc[] getCameraList();
+
+    /**
+     * Returns a list of all EVS displays available to the system
+     *
+     * @return Identifiers of available displays.
+     */
+    byte[] getDisplayIdList();
+
+    /**
+     * This call requests the current state of the display
+     *
+     * If there is no open display, this returns DisplayState::NOT_OPEN. otherwise, it returns
+     * the actual state of the active display.  This call is replicated on the IEvsEnumerator
+     * interface in order to allow secondary clients to monitor the state of the EVS display
+     * without acquiring exclusive ownership of the display.
+     *
+     * @return Current DisplayState of this Display.
+     * @throws EvsResult::OWNERSHIP_LOST if current display is inactive
+     *        EvsResult::PERMISSION_DENIED if the process is not permitted to do this operation.
+     */
+    DisplayState getDisplayState();
+
+    /**
+     * Return a list of the stream configurations a target camera device supports
+     *
+     * @param in description A target camera descriptor
+     * @return A list of stream configurations supported by a given camera device
+     */
+    Stream[] getStreamList(in CameraDesc description);
+
+    /**
+     * Returns a list of all ultrasonics array available to the system.
+     * Will return an empty vector if ultrasonics is not supported.
+     *
+     * @return A list of ultrasonics available for EVS service.
+     */
+    UltrasonicsArrayDesc[] getUltrasonicsArrayList();
+
+    /**
+     * Tells whether this is EvsManager or HAL implementation.
+     *
+     * @return False for EvsManager implementations and true for all others.
+     */
+    boolean isHardware();
+
+    /**
+     * Gets the IEvsCamera associated with a cameraId from a CameraDesc
+     *
+     * Given a camera's unique cameraId from CameraDesc, returns the
+     * IEvsCamera interface associated with the specified camera. When
+     * done using the camera, the caller may release it by calling closeCamera().
+     *
+     * @param in cameraId  A unique identifier of the camera.
+     * @param in streamCfg A stream configuration the client wants to use.
+     * @return EvsCamera object associated with a given cameraId.
+     *         Returned object would be null if a camera device does not support a
+     *         given stream configuration or is already configured differently by
+     *         another client.
+     * @throws EvsResult::PERMISSION_DENIED if the process is not permitted to use camera
+     *        devices.
+     *        EveResult::INVALID_ARG if it fails to open a camera with a given id.
+     */
+    IEvsCamera openCamera(in String cameraId, in Stream streamCfg);
+
+    /**
+     * Get exclusive access to IEvsDisplay for the system
+     *
+     * There can be more than one EVS display objects for the system and this function
+     * requests access to the display identified by a given ID. If the target EVS display
+     * is not available or is already in use the old instance shall be closed and give
+     * the new caller exclusive access.
+     * When done using the display, the caller may release it by calling closeDisplay().
+     *
+     * @param in id Target display identifier.
+     * @return EvsDisplay object to be used.
+     * @throws EvsResult::INVALID_ARG if no display with a given id exists
+     */
+    IEvsDisplay openDisplay(in byte id);
+
+    /**
+     * Gets the IEvsUltrasonicsArray associated with a ultrasonicsArrayId from a
+     * UltrasonicsDataDesc
+     *
+     * @param in ultrasonicsArrayId A unique identifier of the ultrasonic array.
+     * @return IEvsUltrasonicsArray object associated with a given ultrasonicsArrayId.
+     */
+    IEvsUltrasonicsArray openUltrasonicsArray(in String ultrasonicsArrayId);
+
+    /**
+     * Registers a callback to listen to devices' status changes
+     *
+     * @param in callback IEvsEnumeratorStatusCallback implementation
+     */
+    void registerStatusCallback(in IEvsEnumeratorStatusCallback callback);
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl
new file mode 100644
index 0000000..26ccf72
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.DeviceStatus;
+
+/**
+ * Implemented on client side to receive asynchronous notifications from
+ * IEvsEnumreator.
+ */
+@VintfStability
+oneway interface IEvsEnumeratorStatusCallback {
+    /**
+     * Receives calls from the HAL each time a status of camera devices is
+     * changed.
+     *
+     * @param in status A list of newly updated device status
+     */
+    void deviceStatusChanged(in DeviceStatus[] status);
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl
new file mode 100644
index 0000000..40de313
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.aidl
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.IEvsUltrasonicsArrayStream;
+import android.hardware.automotive.evs.UltrasonicsArrayDesc;
+import android.hardware.automotive.evs.UltrasonicsDataFrameDesc;
+
+/**
+ * HAL interface for ultrasonics sensor array.
+ */
+@VintfStability
+interface IEvsUltrasonicsArray {
+    /**
+     * Notifies the UltrasonicsDataDesc is consumed that was received from
+     * IEvsUltrasonicsArrayStream
+     *
+     * @param in dataFrameDesc Ultrasonics data descriptor
+     */
+    void doneWithDataFrame(in UltrasonicsDataFrameDesc dataFrameDesc);
+
+    /**
+     * Returns the ultrasonic sensor array information
+     *
+     * @throws The description of this ultrasonic array. This must be the same
+     *        value as reported by IEvsEnumerator::getUltrasonicsArrayList().
+     */
+    UltrasonicsArrayDesc getUltrasonicArrayInfo();
+
+    /**
+     * Specifies the depth of the buffer chain the ultrasonic sensors is
+     * asked to support
+     *
+     * Up to this many data frames may be held concurrently by the client of IEvsUltrasonicsArray.
+     * If this many frames have been delivered to the receiver without being returned
+     * by doneWithFrame, the stream must skip frames until a buffer is returned for reuse.
+     * It is legal for this call to come at any time, even while streams are already running,
+     * in which case buffers should be added or removed from the chain as appropriate.
+     * If no call is made to this entry point, the IEvsUltrasonicsArray must support at least one
+     * data frame by default. More is acceptable.
+     *
+     * @param in bufferCount Number of buffers the client of IEvsUltrasonicsArray may hold
+     *           concurrently.
+     * @throws EvsResult::INVALID_ARG on invalid bufferCount.
+     */
+    void setMaxFramesInFlight(in int bufferCount);
+
+    /**
+     * Requests to start the stream
+     *
+     * @param in stream Implementation of IEvsUltrasonicsArrayStream.
+     * @throws EvsResult::STREAM_ALREADY_RUNNING if stream is already running
+     */
+    void startStream(in IEvsUltrasonicsArrayStream stream);
+
+    /**
+     * Requests to stop the delivery of the ultrasonic array data frames
+     *
+     * Because delivery is asynchronous, frames may continue to arrive for
+     * some time after this call returns. Each must be returned until the
+     * closure of the stream is signaled to the IEvsCameraStream.
+     * This function cannot fail and is ignored if the stream isn't running.
+     */
+    void stopStream();
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl
new file mode 100644
index 0000000..bc31a6b
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsUltrasonicsArrayStream.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.EvsEventDesc;
+import android.hardware.automotive.evs.UltrasonicsDataFrameDesc;
+
+/**
+ * Implemented on client side to receive asynchronous ultrasonic data
+ * deliveries.
+ */
+@VintfStability
+interface IEvsUltrasonicsArrayStream {
+    /**
+     * Receives calls from the HAL each time a data frame is ready
+     *
+     * @param in dataFrameDesc Ultrasonic array data frame descriptor
+     */
+    oneway void deliverDataFrame(in UltrasonicsDataFrameDesc dataFrameDesc);
+
+    /**
+     * Receives calls from the HAL each time an event happens
+     *
+     * @param in event Event EVS event with possible event information
+     */
+    oneway void notify(in EvsEventDesc event);
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/ParameterRange.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/ParameterRange.aidl
new file mode 100644
index 0000000..b08fcbd
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/ParameterRange.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+/**
+ * Represent a valid range of CameraParam
+ */
+@VintfStability
+parcelable ParameterRange {
+    /**
+     * Lower bound of a valid value range
+     */
+    int min;
+    /**
+     * Upper bound of a valid value range
+     */
+    int max;
+    /**
+     * A value of unit increment
+     */
+    int step;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/Rotation.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/Rotation.aidl
new file mode 100644
index 0000000..dede39e
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/Rotation.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+/**
+ * Rotation:
+ *
+ * The required counterclockwise rotation of EVS camera stream and display.
+ */
+@VintfStability
+@Backing(type="int")
+enum Rotation {
+    /** No rotation */
+    ROTATION_0 = 0,
+    /** Rotate by 90 degree counterclockwise */
+    ROTATION_90 = 1,
+    /** Rotate by 180 degree counterclockwise */
+    ROTATION_180 = 2,
+    /** Rotate by 270 degree counterclockwise */
+    ROTATION_270 = 3
+
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/RotationQuaternion.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/RotationQuaternion.aidl
new file mode 100644
index 0000000..b80343b
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/RotationQuaternion.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+/**
+ * Structure for rotation expressed as quaternions.
+ * Convention used: Unit quaternion with hamilton convention.
+ */
+@VintfStability
+parcelable RotationQuaternion {
+    float x;
+    float y;
+    float z;
+    float w;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/SensorPose.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/SensorPose.aidl
new file mode 100644
index 0000000..26c3339
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/SensorPose.aidl
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.RotationQuaternion;
+import android.hardware.automotive.evs.Translation;
+
+/**
+ * Provides the orientation and location of a car sensor relative to the android automotive
+ * coordinate system:
+ * https://source.android.com/devices/sensors/sensor-types#auto_axes
+ * The sensor pose defines the transformation to be applied to the android automotive axes to
+ * obtain the sensor local axes.
+ * The pose consists of rotation, (specified as a quaternions) and translation
+ * (vector with x, y, z).
+ * This rotation and translation applied to the sensor data in the sensor's local coordinate
+ * system transform the data to the automotive coordinate system.
+ * i.e.  loc =  ( Rot * Psensor ) + Trans
+ * Here loc is a point in automotive coordinate system and Psensor is a point in the sensor's
+ * coordinate system.
+ * Example:
+ * For a sensor on the front bumper and on the left corner of the car with its X axis pointing to
+ * the front, the sensor is located at (-2, 4, 0) meters w.r.t android automotive axes and the
+ * sensor local axes has a rotation of 90 degrees counter-clockwise w.r.t android automotive axes
+ * when viewing the car from top on the +Z axis side:
+ *
+ *      ↑X sensor
+ *    Y←∘______
+ *      |      |  front
+ *      | car  |
+ *      |  ↑Y  |
+ *      |  ∘→X |  rear
+ *      |______|
+ *
+ * For this example the rotation and translation will be:
+ * Rotation = + 90 degrees around Z axis = (0.7071, 0, 0, 0.7071) as a unit quaternion.
+ * Translation = (-2, 4, 0) in meters = (-2000, 4000, 0) in milli-meters.
+ * Note: Every sensor type must specify its own pose.
+ */
+@VintfStability
+parcelable SensorPose {
+    /**
+     * Rotation part of the sensor pose, expressed as a unit quaternion.
+     */
+    RotationQuaternion rotation;
+    /**
+     * Translation part of the sensor pose, in (x, y, z) format with milli-meter units.
+     */
+    Translation translation;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/Stream.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/Stream.aidl
new file mode 100644
index 0000000..ae5c7f0
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/Stream.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.Rotation;
+import android.hardware.automotive.evs.StreamType;
+import android.hardware.graphics.common.BufferUsage;
+import android.hardware.graphics.common.PixelFormat;
+
+/**
+ * Stream:
+ *
+ * Structure that describes a EVS Camera stream
+ */
+@VintfStability
+parcelable Stream {
+    /**
+     * Stream ID - a non-negative integer identifier for a stream.
+     *
+     * The identical stream ID must reference the same stream, with the same
+     * width/height/format, across consecutive calls to configureStreams.
+     *
+     * If previously-used stream ID is not used in a new call to
+     * configureStreams, then that stream is no longer active. Such a stream ID
+     * may be reused in a future configureStreams with a new
+     * width/height/format.
+     *
+     */
+    int id;
+    /**
+     * The type of the stream (input vs output, etc).
+     */
+    StreamType streamType;
+    /**
+     * The width in pixels of the buffers in this stream.
+     */
+    int width;
+    /**
+     * The height in pixels of the buffers in this stream.
+     */
+    int height;
+    /**
+     * The frame rate of this stream in frames-per-second
+     /
+    int framerate;
+    /**
+     * The pixel format form the buffers in this stream.
+     */
+    PixelFormat format;
+    /**
+     * The gralloc usage flags for this stream, as needed by the consumer of
+     * the stream.
+     */
+    BufferUsage usage;
+    /**
+     * The required output rotation of the stream.
+     *
+     * This must be inspected by HAL along with stream with and height.
+     */
+    Rotation rotation;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/StreamType.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/StreamType.aidl
new file mode 100644
index 0000000..c028a5c
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/StreamType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+/**
+ * StreamType:
+ *
+ * The type of the camera stream, which defines whether the EVS client device is
+ * the producer or the consumer for that stream, and how the buffers of the
+ * stream relate to the other streams.
+ */
+@VintfStability
+@Backing(type="int")
+enum StreamType {
+    /**
+     * This stream is an output stream; the EVS HAL device must fill buffers
+     * from this stream with newly captured or reprocessed image data.
+     */
+    OUTPUT = 0,
+
+    /**
+     * This stream is an input stream; the EVS HAL device must read buffers
+     * from this stream and send them through the camera processing pipeline,
+     * as if the buffer was a newly captured image from the imager.
+     */
+    INPUT = 1
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/Translation.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/Translation.aidl
new file mode 100644
index 0000000..14b14db
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/Translation.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+/**
+ * Structure for translation with x, y and z units.
+ */
+@VintfStability
+parcelable Translation {
+    float x;
+    float y;
+    float z;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicSensor.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicSensor.aidl
new file mode 100644
index 0000000..712411b
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicSensor.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.SensorPose;
+
+/**
+ * Structure that contains all information of an ultrasonic sensor.
+ */
+@VintfStability
+parcelable UltrasonicSensor {
+    /**
+     * Pose provides the orientation and location of the ultrasonic sensor within the car.
+     * The +Y axis points along the center of the beam spread the X axis to the right and the Z
+     * axis in the up direction.
+     */
+    SensorPose pose;
+    /**
+     * Maximum range of the sensor in milli-metres.
+     */
+    float maxRangeMm;
+    /**
+     * Half-angle of the angle of measurement of the sensor, relative to the
+     * sensor’s x axis, in radians.
+     */
+    float angleOfMeasurement;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl
new file mode 100644
index 0000000..d4f0663
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsArrayDesc.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.automotive.evs.UltrasonicSensor;
+
+/**
+ * Structure identifies and describes an ultrasonics array in the car.
+ *
+ * A ultrasonics array represents a group of ultrasonic sensors within the
+ * car. These may be sensors that are physically connected to the same hardware
+ * control unit or represent a logical group of sensors like front and back.
+ * The HAL is responsible for filling out this structure for each Ultrasonics
+ * Array.
+ */
+@VintfStability
+parcelable UltrasonicsArrayDesc {
+    /**
+     * Unique identifier for the ultrasonic array. This may be a path or name of the
+     * physical control device or a string identifying a logical group of sensors forming an array
+     * such as "front_array" and "back_array".
+     */
+    @utf8InCpp
+    String ultrasonicsArrayId;
+    /**
+     * Maximum number of readings (points on waveform) provided per sensor in
+     * each data frame. Used by client to pre-allocate required memory buffer for
+     * incoming data.
+     */
+    int maxReadingsPerSensorCount;
+    /**
+     * Maximum number of receiver sensors in a data frame. Must be between 1
+     * and sensorCount. Used by client to pre-allocate required memory buffer for
+     * incoming data.
+     */
+    int maxReceiversCount;
+    /**
+     * The order of sensors specified must be in clockwise order around the car, starting
+     * from front left-most sensor.
+     */
+    UltrasonicSensor[] sensors;
+}
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl
new file mode 100644
index 0000000..e546db9
--- /dev/null
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.aidl
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.evs;
+
+import android.hardware.common.Ashmem;
+
+/**
+ * Structure that describes the data frame received from an ultrasonics array.
+ *
+ * Each data frame returned consists of received waveform signals from a subset
+ * of sensors in an array as indicated by the receiversIdList. The signal is
+ * transmitted at a particular time instant indicated by timestampNs from a
+ * subset of sensors in the array as provided in the transmittersIdList.
+ */
+@VintfStability
+parcelable UltrasonicsDataFrameDesc {
+    /**
+     * Timestamp of the start of the transmit signal for this data frame.
+     * Timestamp unit is nanoseconds and is obtained from android::elapsedRealtimeNanos().
+     * timeOfFlight readings are future-deltas to this timestamp.
+     */
+    long timestampNs;
+    /**
+     * Identifier of data frame. Used by implementation for managing multiple frames in flight.
+     */
+    int id;
+    /**
+     * List of indexes of sensors in range [0, sensorCount - 1] that
+     * transmitted the signal for this data frame.
+     */
+    byte[] transmittersIdList;
+    /**
+     * List of indexes of sensors in range [0, sensorCount - 1] that received
+     * the signal. The order of ids must match the order of the waveforms in the
+     * waveformsData.
+     * Size of list is upper bound by maxReceiversCount.
+     */
+    byte[] receiversIdList;
+    /**
+     * List of the number of readings corresponding to each ultrasonics sensor in
+     * the receiversIdList. Order of the readings count must match the order in
+     * receiversIdList.
+     * Size of list is upper bound by maxReadingsPerSensorCount.
+     */
+    int[] receiversReadingsCountList;
+    /**
+     * Shared memory object containing the waveforms data. Contains one waveform
+     * for each sensor specified in receiversIdList, in order.
+     * Each waveform is represented by a number of readings, which are sample
+     * points on the waveform. The number of readings for each waveform is as
+     * specified in the receiversReadingsCountList.
+     * Each reading is a pair of time Of flight and resonance.
+     * Time of flight (float): Time between transmit and receive signal in nanoseconds.
+     * Resonance (float): Resonance at time on waveform in range [0.0, 1.0].
+     *
+     * The structure of shared memory (example with 2 waveforms, each with 2 readings):
+     *
+     * Byte: |   0    |  1-4  |  5-8  | 9-12  | 13-16 ||   17   |  18-21 | 22-25  | 26-29 | 30-33 |
+     * Data: | RecId1 | TOF1  | RES1  | TOF2  | RES2  || RecId2 |  TOF1  |  RES1  | TOF2  | RES2  |
+     *       |              Waveform1                 ||             Waveform2                    |
+     * Here:
+     * RecId : Receiver's Id. Order matches the receiversIdList, type uint8_t
+     * TOF : Time of flight, type float (4 bytes)
+     * RES : Resonance, type float (4 bytes)
+     * Note: All readings and waveforms are contigious with no padding.
+     */
+    Ashmem waveformsData;
+}
diff --git a/automotive/evs/aidl/impl/Android.bp b/automotive/evs/aidl/impl/Android.bp
new file mode 100644
index 0000000..7eb0116
--- /dev/null
+++ b/automotive/evs/aidl/impl/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_defaults {
+    name: "EvsHalDefaults",
+    static_libs: [
+        "android.hardware.automotive.evs-V1-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.graphics.common-V3-ndk",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libutils",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+}
diff --git a/automotive/evs/aidl/impl/default/Android.bp b/automotive/evs/aidl/impl/default/Android.bp
new file mode 100644
index 0000000..dbe0314
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+    name: "android.hardware.automotive.evs-aidl-default-service",
+    defaults: ["EvsHalDefaults"],
+    local_include_dirs: ["include"],
+    vintf_fragments: ["evs-default-service.xml"],
+    init_rc: ["evs-default-service.rc"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: ["src/*.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+}
diff --git a/automotive/evs/aidl/impl/default/evs-default-service.rc b/automotive/evs/aidl/impl/default/evs-default-service.rc
new file mode 100644
index 0000000..ea8e689
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/evs-default-service.rc
@@ -0,0 +1,5 @@
+service vendor.evs-hal-default /vendor/bin/hw/android.hardware.automotive.evs-aidl-default-service
+    class early_hal
+    user automotive_evs
+    group automotive_evs
+    disabled
diff --git a/automotive/evs/aidl/impl/default/evs-default-service.xml b/automotive/evs/aidl/impl/default/evs-default-service.xml
new file mode 100644
index 0000000..96ff9f6
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/evs-default-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.automotive.evs</name>
+        <transport>hwbinder</transport>
+        <version>1</version>
+        <interface>
+            <name>IEvsEnumerator</name>
+            <instance>hw/0</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/automotive/evs/aidl/impl/default/include/DefaultEvsEnumerator.h b/automotive/evs/aidl/impl/default/include/DefaultEvsEnumerator.h
new file mode 100644
index 0000000..8bcd867
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/include/DefaultEvsEnumerator.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.
+ */
+
+#ifndef android_hardware_automotive_evs_aidl_impl_evshal_include_DefaultEvsHal_H_
+#define android_hardware_automotive_evs_aidl_impl_evshal_include_DefaultEvsHal_H_
+
+#include <aidl/android/hardware/automotive/evs/BnEvsEnumerator.h>
+
+namespace aidl::android::hardware::automotive::evs::implementation {
+
+class DefaultEvsEnumerator final
+    : public ::aidl::android::hardware::automotive::evs::BnEvsEnumerator {
+    ::ndk::ScopedAStatus isHardware(bool* flag) override;
+    ::ndk::ScopedAStatus openCamera(
+            const std::string& cameraId,
+            const ::aidl::android::hardware::automotive::evs::Stream& streamConfig,
+            std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsCamera>* obj) override;
+    ::ndk::ScopedAStatus closeCamera(
+            const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsCamera>& obj)
+            override;
+    ::ndk::ScopedAStatus getCameraList(
+            std::vector<::aidl::android::hardware::automotive::evs::CameraDesc>* list) override;
+    ::ndk::ScopedAStatus getStreamList(
+            const ::aidl::android::hardware::automotive::evs::CameraDesc& desc,
+            std::vector<::aidl::android::hardware::automotive::evs::Stream>* _aidl_return) override;
+    ::ndk::ScopedAStatus openDisplay(
+            int8_t displayId,
+            std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay>* obj) override;
+    ::ndk::ScopedAStatus closeDisplay(
+            const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay>& obj)
+            override;
+    ::ndk::ScopedAStatus getDisplayIdList(std::vector<uint8_t>* list) override;
+    ::ndk::ScopedAStatus getDisplayState(
+            ::aidl::android::hardware::automotive::evs::DisplayState* state) override;
+    ::ndk::ScopedAStatus registerStatusCallback(
+            const std::shared_ptr<
+                    ::aidl::android::hardware::automotive::evs::IEvsEnumeratorStatusCallback>&
+                    callback) override;
+    ::ndk::ScopedAStatus openUltrasonicsArray(
+            const std::string& id,
+            std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray>* obj)
+            override;
+    ::ndk::ScopedAStatus closeUltrasonicsArray(
+            const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray>&
+                    arr) override;
+    ::ndk::ScopedAStatus getUltrasonicsArrayList(
+            std::vector<::aidl::android::hardware::automotive::evs::UltrasonicsArrayDesc>* list)
+            override;
+};
+
+}  // namespace aidl::android::hardware::automotive::evs::implementation
+
+#endif  // android_hardware_automotive_evs_aidl_impl_evshal_include_DefaultEvsHal_H_
diff --git a/automotive/evs/aidl/impl/default/src/DefaultEvsEnumerator.cpp b/automotive/evs/aidl/impl/default/src/DefaultEvsEnumerator.cpp
new file mode 100644
index 0000000..2ff6d59
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/src/DefaultEvsEnumerator.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO(b/203661081): Remove below lines to disable compiler warnings.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+
+#define LOG_TAG "DefaultEvsEnumerator"
+
+#include <DefaultEvsEnumerator.h>
+
+namespace aidl::android::hardware::automotive::evs::implementation {
+
+using ::ndk::ScopedAStatus;
+
+ScopedAStatus DefaultEvsEnumerator::isHardware(bool* flag) {
+    // This returns true always.
+    *flag = true;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::openCamera(const std::string& cameraId,
+                                               const Stream& streamConfig,
+                                               std::shared_ptr<IEvsCamera>* obj) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::closeCamera(const std::shared_ptr<IEvsCamera>& obj) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::getCameraList(std::vector<CameraDesc>* list) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::getStreamList(const CameraDesc& desc,
+                                                  std::vector<Stream>* _aidl_return) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::openDisplay(int8_t displayId,
+                                                std::shared_ptr<IEvsDisplay>* obj) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::closeDisplay(const std::shared_ptr<IEvsDisplay>& state) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::getDisplayIdList(std::vector<uint8_t>* list) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::getDisplayState(DisplayState* state) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::registerStatusCallback(
+        const std::shared_ptr<IEvsEnumeratorStatusCallback>& callback) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::openUltrasonicsArray(
+        const std::string& id, std::shared_ptr<IEvsUltrasonicsArray>* obj) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::closeUltrasonicsArray(
+        const std::shared_ptr<IEvsUltrasonicsArray>& obj) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultEvsEnumerator::getUltrasonicsArrayList(
+        std::vector<UltrasonicsArrayDesc>* list) {
+    return ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::automotive::evs::implementation
+
+#pragma clang diagnostic pop
diff --git a/automotive/evs/aidl/impl/default/src/service.cpp b/automotive/evs/aidl/impl/default/src/service.cpp
new file mode 100644
index 0000000..0a0913f
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/src/service.cpp
@@ -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.
+ */
+
+#define LOG_TAG "EvsService"
+
+#include <DefaultEvsEnumerator.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <utils/Log.h>
+
+using ::aidl::android::hardware::automotive::evs::implementation::DefaultEvsEnumerator;
+
+int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
+    std::shared_ptr<DefaultEvsEnumerator> vhal = ndk::SharedRefBase::make<DefaultEvsEnumerator>();
+
+    ALOGI("Registering as service...");
+    binder_exception_t err =
+            AServiceManager_addService(vhal->asBinder().get(), "android.hardware.automotive.evs");
+    if (err != EX_NONE) {
+        ALOGE("failed to register android.hardware.automotive.evs service, exception: %d", err);
+        return 1;
+    }
+
+    if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) {
+        ALOGE("%s", "failed to set thread pool max thread count");
+        return 1;
+    }
+    ABinderProcess_startThreadPool();
+
+    ALOGI("Evs Service Ready");
+
+    ABinderProcess_joinThreadPool();
+
+    ALOGI("Evs Service Exiting");
+
+    return 0;
+}
diff --git a/automotive/evs/aidl/vts/Android.bp b/automotive/evs/aidl/vts/Android.bp
new file mode 100644
index 0000000..980c6d5
--- /dev/null
+++ b/automotive/evs/aidl/vts/Android.bp
@@ -0,0 +1,53 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package{
+    // 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:
+    "VtsHalEvsTargetTest",
+    srcs: [
+        "*.cpp",
+    ],
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libcamera_metadata",
+        "libui",
+        "libutils",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib",
+        "android.hardware.automotive.evs-V1-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.graphics.common-V3-ndk",
+        "libaidlcommonsupport",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/automotive/evs/aidl/vts/FrameHandler.cpp b/automotive/evs/aidl/vts/FrameHandler.cpp
new file mode 100644
index 0000000..bab832b
--- /dev/null
+++ b/automotive/evs/aidl/vts/FrameHandler.cpp
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalEvsTest"
+
+#include "FrameHandler.h"
+#include "FormatConvert.h"
+
+#include <aidl/android/hardware/graphics/common/HardwareBufferDescription.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android-base/logging.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+
+using ::aidl::android::hardware::automotive::evs::BufferDesc;
+using ::aidl::android::hardware::automotive::evs::CameraDesc;
+using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
+using ::aidl::android::hardware::automotive::evs::EvsEventType;
+using ::aidl::android::hardware::automotive::evs::IEvsCamera;
+using ::aidl::android::hardware::automotive::evs::IEvsDisplay;
+using ::aidl::android::hardware::graphics::common::HardwareBufferDescription;
+using ::ndk::ScopedAStatus;
+using std::chrono_literals::operator""s;
+
+FrameHandler::FrameHandler(const std::shared_ptr<IEvsCamera>& pCamera, const CameraDesc& cameraInfo,
+                           const std::shared_ptr<IEvsDisplay>& pDisplay, BufferControlFlag mode)
+    : mCamera(pCamera), mCameraInfo(cameraInfo), mDisplay(pDisplay), mReturnMode(mode) {
+    // Nothing but member initialization here.
+}
+
+void FrameHandler::shutdown() {
+    // Make sure we're not still streaming
+    blockingStopStream();
+
+    // At this point, the receiver thread is no longer running, so we can safely drop
+    // our remote object references so they can be freed
+    mCamera = nullptr;
+    mDisplay = nullptr;
+}
+
+bool FrameHandler::startStream() {
+    // Tell the camera to start streaming
+    auto status = mCamera->startVideoStream(ref<FrameHandler>());
+    if (!status.isOk()) {
+        return false;
+    }
+
+    // Mark ourselves as running
+    mLock.lock();
+    mRunning = true;
+    mLock.unlock();
+
+    return true;
+}
+
+void FrameHandler::asyncStopStream() {
+    // Tell the camera to stop streaming.
+    // This will result in a null frame being delivered when the stream actually stops.
+    mCamera->stopVideoStream();
+}
+
+void FrameHandler::blockingStopStream() {
+    // Tell the stream to stop
+    asyncStopStream();
+
+    // Wait until the stream has actually stopped
+    std::unique_lock<std::mutex> lock(mEventLock);
+    if (mRunning) {
+        mEventSignal.wait(lock, [this]() { return !mRunning; });
+    }
+}
+
+bool FrameHandler::returnHeldBuffer() {
+    std::lock_guard<std::mutex> lock(mLock);
+
+    // Return the oldest buffer we're holding
+    if (mHeldBuffers.empty()) {
+        // No buffers are currently held
+        return false;
+    }
+
+    std::vector<BufferDesc> buffers = std::move(mHeldBuffers.front());
+    mHeldBuffers.pop();
+    mCamera->doneWithFrame(buffers);
+
+    return true;
+}
+
+bool FrameHandler::isRunning() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return mRunning;
+}
+
+void FrameHandler::waitForFrameCount(unsigned frameCount) {
+    // Wait until we've seen at least the requested number of frames (could be more)
+    std::unique_lock<std::mutex> lock(mLock);
+    mFrameSignal.wait(lock, [this, frameCount]() { return mFramesReceived >= frameCount; });
+}
+
+void FrameHandler::getFramesCounters(unsigned* received, unsigned* displayed) {
+    std::lock_guard<std::mutex> lock(mLock);
+
+    if (received) {
+        *received = mFramesReceived;
+    }
+    if (displayed) {
+        *displayed = mFramesDisplayed;
+    }
+}
+
+ScopedAStatus FrameHandler::deliverFrame(const std::vector<BufferDesc>& buffers) {
+    mLock.lock();
+    // For VTS tests, FrameHandler uses a single frame among delivered frames.
+    auto bufferIdx = mFramesDisplayed % buffers.size();
+    auto& buffer = buffers[bufferIdx];
+    mLock.unlock();
+
+    // Store a dimension of a received frame.
+    mFrameWidth = buffer.buffer.description.width;
+    mFrameHeight = buffer.buffer.description.height;
+
+    // If we were given an opened display at construction time, then send the received
+    // image back down the camera.
+    bool displayed = false;
+    if (mDisplay) {
+        // Get the output buffer we'll use to display the imagery
+        BufferDesc tgtBuffer;
+        auto status = mDisplay->getTargetBuffer(&tgtBuffer);
+        if (!status.isOk()) {
+            printf("Didn't get target buffer - frame lost\n");
+            LOG(ERROR) << "Didn't get requested output buffer -- skipping this frame.";
+        } else {
+            // Copy the contents of the of buffer.memHandle into tgtBuffer
+            copyBufferContents(tgtBuffer, buffer);
+
+            // Send the target buffer back for display
+            auto status = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
+            if (!status.isOk()) {
+                printf("AIDL error on display buffer (%d)- frame lost\n",
+                       status.getServiceSpecificError());
+                LOG(ERROR) << "Error making the remote function call.  AIDL said "
+                           << status.getServiceSpecificError();
+            } else {
+                // Everything looks good!
+                // Keep track so tests or watch dogs can monitor progress
+                displayed = true;
+            }
+        }
+    }
+
+    mLock.lock();
+    // increases counters
+    ++mFramesReceived;
+    mFramesDisplayed += (int)displayed;
+    mLock.unlock();
+    mFrameSignal.notify_all();
+
+    switch (mReturnMode) {
+        case eAutoReturn:
+            // Send the camera buffer back now that the client has seen it
+            LOG(DEBUG) << "Calling doneWithFrame";
+            mCamera->doneWithFrame(buffers);
+            break;
+        case eNoAutoReturn:
+            // Hang onto the buffer handles for now -- the client will return it explicitly later
+            // mHeldBuffers.push(buffers);
+            break;
+    }
+
+    LOG(DEBUG) << "Frame handling complete";
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus FrameHandler::notify(const EvsEventDesc& event) {
+    // Local flag we use to keep track of when the stream is stopping
+    std::unique_lock<std::mutex> lock(mEventLock);
+    mLatestEventDesc.aType = event.aType;
+    mLatestEventDesc.payload[0] = event.payload[0];
+    mLatestEventDesc.payload[1] = event.payload[1];
+    if (mLatestEventDesc.aType == EvsEventType::STREAM_STOPPED) {
+        // Signal that the last frame has been received and the stream is stopped
+        mRunning = false;
+    } else if (mLatestEventDesc.aType == EvsEventType::PARAMETER_CHANGED) {
+        LOG(DEBUG) << "Camera parameter " << mLatestEventDesc.payload[0] << " is changed to "
+                   << mLatestEventDesc.payload[1];
+    } else {
+        LOG(DEBUG) << "Received an event " << eventToString(mLatestEventDesc.aType);
+    }
+    lock.unlock();
+    mEventSignal.notify_one();
+
+    return ScopedAStatus::ok();
+}
+
+bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer, const BufferDesc& srcBuffer) {
+    bool success = true;
+    const HardwareBufferDescription* pSrcDesc =
+            reinterpret_cast<const HardwareBufferDescription*>(&srcBuffer.buffer.description);
+    const HardwareBufferDescription* pTgtDesc =
+            reinterpret_cast<const HardwareBufferDescription*>(&tgtBuffer.buffer.description);
+
+    // Make sure we don't run off the end of either buffer
+    const unsigned width = std::min(pTgtDesc->width, pSrcDesc->width);
+    const unsigned height = std::min(pTgtDesc->height, pSrcDesc->height);
+
+    // FIXME: We duplicate file descriptors twice below; consider using TAKE_HANDLE
+    // instead of CLONE_HANDLE.
+    buffer_handle_t target = ::android::dupFromAidl(tgtBuffer.buffer.handle);
+    ::android::sp<android::GraphicBuffer> tgt = new android::GraphicBuffer(
+            target, android::GraphicBuffer::CLONE_HANDLE, pTgtDesc->width, pTgtDesc->height,
+            static_cast<android::PixelFormat>(pTgtDesc->format), pTgtDesc->layers,
+            static_cast<uint64_t>(pTgtDesc->usage), pTgtDesc->stride);
+
+    buffer_handle_t source = ::android::dupFromAidl(srcBuffer.buffer.handle);
+    ::android::sp<android::GraphicBuffer> src = new android::GraphicBuffer(
+            source, android::GraphicBuffer::CLONE_HANDLE, pSrcDesc->width, pSrcDesc->height,
+            static_cast<android::PixelFormat>(pSrcDesc->format), pSrcDesc->layers,
+            static_cast<uint64_t>(pSrcDesc->usage), pSrcDesc->stride);
+
+    // Lock our source buffer for reading (current expectation are for this to be NV21 format)
+    uint8_t* srcPixels = nullptr;
+    src->lock(GRALLOC_USAGE_SW_READ_OFTEN, (void**)&srcPixels);
+
+    // Lock our target buffer for writing (should be either RGBA8888 or BGRA8888 format)
+    uint32_t* tgtPixels = nullptr;
+    tgt->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)&tgtPixels);
+
+    if (srcPixels && tgtPixels) {
+        using namespace ::android::hardware::automotive::evs::common;
+        if (static_cast<android_pixel_format_t>(pTgtDesc->format) == HAL_PIXEL_FORMAT_RGBA_8888) {
+            if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+                HAL_PIXEL_FORMAT_YCRCB_420_SP) {  // 420SP == NV21
+                Utils::copyNV21toRGB32(width, height, srcPixels, tgtPixels, pTgtDesc->stride);
+            } else if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+                       HAL_PIXEL_FORMAT_YV12) {  // YUV_420P == YV12
+                Utils::copyYV12toRGB32(width, height, srcPixels, tgtPixels, pTgtDesc->stride);
+            } else if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+                       HAL_PIXEL_FORMAT_YCBCR_422_I) {  // YUYV
+                Utils::copyYUYVtoRGB32(width, height, srcPixels, pSrcDesc->stride, tgtPixels,
+                                       pTgtDesc->stride);
+            } else if (pSrcDesc->format == pTgtDesc->format) {  // 32bit RGBA
+                Utils::copyMatchedInterleavedFormats(width, height, srcPixels, pSrcDesc->stride,
+                                                     tgtPixels, pTgtDesc->stride,
+                                                     tgtBuffer.pixelSizeBytes);
+            } else {
+                LOG(ERROR) << "Camera buffer format is not supported";
+                success = false;
+            }
+        } else if (static_cast<android_pixel_format_t>(pTgtDesc->format) ==
+                   HAL_PIXEL_FORMAT_BGRA_8888) {
+            if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+                HAL_PIXEL_FORMAT_YCRCB_420_SP) {  // 420SP == NV21
+                Utils::copyNV21toBGR32(width, height, srcPixels, tgtPixels, pTgtDesc->stride);
+            } else if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+                       HAL_PIXEL_FORMAT_YV12) {  // YUV_420P == YV12
+                Utils::copyYV12toBGR32(width, height, srcPixels, tgtPixels, pTgtDesc->stride);
+            } else if (static_cast<android_pixel_format_t>(pSrcDesc->format) ==
+                       HAL_PIXEL_FORMAT_YCBCR_422_I) {  // YUYV
+                Utils::copyYUYVtoBGR32(width, height, srcPixels, pSrcDesc->stride, tgtPixels,
+                                       pTgtDesc->stride);
+            } else if (pSrcDesc->format == pTgtDesc->format) {  // 32bit RGBA
+                Utils::copyMatchedInterleavedFormats(width, height, srcPixels, pSrcDesc->stride,
+                                                     tgtPixels, pTgtDesc->stride,
+                                                     tgtBuffer.pixelSizeBytes);
+            } else {
+                LOG(ERROR) << "Camera buffer format is not supported";
+                success = false;
+            }
+        } else {
+            // We always expect 32 bit RGB for the display output for now.  Is there a need for 565?
+            LOG(ERROR) << "Diplay buffer is always expected to be 32bit RGBA";
+            success = false;
+        }
+    } else {
+        LOG(ERROR) << "Failed to lock buffer contents for contents transfer";
+        success = false;
+    }
+
+    if (srcPixels) {
+        src->unlock();
+    }
+    if (tgtPixels) {
+        tgt->unlock();
+    }
+
+    return success;
+}
+
+void FrameHandler::getFrameDimension(unsigned* width, unsigned* height) {
+    if (width) {
+        *width = mFrameWidth;
+    }
+
+    if (height) {
+        *height = mFrameHeight;
+    }
+}
+
+bool FrameHandler::waitForEvent(const EvsEventDesc& aTargetEvent, EvsEventDesc& aReceivedEvent,
+                                bool ignorePayload) {
+    // Wait until we get an expected parameter change event.
+    std::unique_lock<std::mutex> lock(mEventLock);
+    auto now = std::chrono::system_clock::now();
+    bool found = false;
+    while (!found) {
+        bool result = mEventSignal.wait_until(
+                lock, now + 5s, [this, aTargetEvent, ignorePayload, &aReceivedEvent, &found]() {
+                    found = (mLatestEventDesc.aType == aTargetEvent.aType) &&
+                            (ignorePayload ||
+                             (mLatestEventDesc.payload[0] == aTargetEvent.payload[0] &&
+                              mLatestEventDesc.payload[1] == aTargetEvent.payload[1]));
+
+                    aReceivedEvent.aType = mLatestEventDesc.aType;
+                    aReceivedEvent.payload[0] = mLatestEventDesc.payload[0];
+                    aReceivedEvent.payload[1] = mLatestEventDesc.payload[1];
+                    return found;
+                });
+
+        if (!result) {
+            LOG(WARNING) << "A timer is expired before a target event has happened.";
+            break;
+        }
+    }
+
+    return found;
+}
+
+const char* FrameHandler::eventToString(const EvsEventType aType) {
+    switch (aType) {
+        case EvsEventType::STREAM_STARTED:
+            return "STREAM_STARTED";
+        case EvsEventType::STREAM_STOPPED:
+            return "STREAM_STOPPED";
+        case EvsEventType::FRAME_DROPPED:
+            return "FRAME_DROPPED";
+        case EvsEventType::TIMEOUT:
+            return "TIMEOUT";
+        case EvsEventType::PARAMETER_CHANGED:
+            return "PARAMETER_CHANGED";
+        case EvsEventType::MASTER_RELEASED:
+            return "MASTER_RELEASED";
+        default:
+            return "Unknown";
+    }
+}
diff --git a/automotive/evs/aidl/vts/FrameHandler.h b/automotive/evs/aidl/vts/FrameHandler.h
new file mode 100644
index 0000000..0b959ab
--- /dev/null
+++ b/automotive/evs/aidl/vts/FrameHandler.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUTOMOTIVE_EVS_VTS_FRAMEHANDLER_H
+#define AUTOMOTIVE_EVS_VTS_FRAMEHANDLER_H
+
+#include <aidl/android/hardware/automotive/evs/BnEvsCameraStream.h>
+#include <aidl/android/hardware/automotive/evs/EvsEventDesc.h>
+#include <aidl/android/hardware/automotive/evs/IEvsCamera.h>
+#include <aidl/android/hardware/automotive/evs/IEvsDisplay.h>
+
+#include <mutex>
+#include <queue>
+
+/*
+ * FrameHandler:
+ * This class can be used to receive camera imagery from an IEvsCamera implementation.  Given an
+ * IEvsDisplay instance at startup, it will forward the received imagery to the display,
+ * providing a trivial implementation of a rear vew camera type application.
+ * Note that the video frames are delivered on a background thread, while the control interface
+ * is actuated from the applications foreground thread.
+ */
+class FrameHandler : public ::aidl::android::hardware::automotive::evs::BnEvsCameraStream {
+  public:
+    enum BufferControlFlag {
+        eAutoReturn,
+        eNoAutoReturn,
+    };
+
+    FrameHandler(
+            const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsCamera>& pCamera,
+            const ::aidl::android::hardware::automotive::evs::CameraDesc& cameraInfo,
+            const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay>&
+                    pDisplay,
+            BufferControlFlag mode = eAutoReturn);
+    virtual ~FrameHandler() {
+        if (mCamera != nullptr) {
+            /* shutdown a camera explicitly */
+            shutdown();
+        }
+    }
+
+    void shutdown();
+    bool startStream();
+    void asyncStopStream();
+    void blockingStopStream();
+    bool returnHeldBuffer();
+    bool isRunning();
+    void waitForFrameCount(unsigned frameCount);
+    bool waitForEvent(const ::aidl::android::hardware::automotive::evs::EvsEventDesc& aTargetEvent,
+                      ::aidl::android::hardware::automotive::evs::EvsEventDesc& aReceivedEvent,
+                      bool ignorePayload = false);
+    void getFramesCounters(unsigned* received, unsigned* displayed);
+    void getFrameDimension(unsigned* width, unsigned* height);
+
+  private:
+    // Methods from ::aidl::android::hardware::automotive::evs::IEvsCameraStream follow.
+    ::ndk::ScopedAStatus deliverFrame(
+            const std::vector<::aidl::android::hardware::automotive::evs::BufferDesc>& buffer)
+            override;
+    ::ndk::ScopedAStatus notify(
+            const ::aidl::android::hardware::automotive::evs::EvsEventDesc& event) override;
+
+    // Local implementation details
+    bool copyBufferContents(
+            const ::aidl::android::hardware::automotive::evs::BufferDesc& tgtBuffer,
+            const ::aidl::android::hardware::automotive::evs::BufferDesc& srcBuffer);
+    const char* eventToString(const ::aidl::android::hardware::automotive::evs::EvsEventType aType);
+
+    std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsCamera> mCamera;
+    ::aidl::android::hardware::automotive::evs::CameraDesc mCameraInfo;
+    std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsDisplay> mDisplay;
+    BufferControlFlag mReturnMode;
+
+    // Since we get frames delivered to us asynchronously via the IEvsCameraStream interface,
+    // we need to protect all member variables that may be modified while we're streaming
+    // (ie: those below)
+    std::mutex mLock;
+    std::mutex mEventLock;
+    std::condition_variable mEventSignal;
+    std::condition_variable mFrameSignal;
+    std::queue<std::vector<::aidl::android::hardware::automotive::evs::BufferDesc>> mHeldBuffers;
+
+    bool mRunning = false;
+    unsigned mFramesReceived = 0;   // Simple counter -- rolls over eventually!
+    unsigned mFramesDisplayed = 0;  // Simple counter -- rolls over eventually!
+    unsigned mFrameWidth = 0;
+    unsigned mFrameHeight = 0;
+    ::aidl::android::hardware::automotive::evs::EvsEventDesc mLatestEventDesc;
+};
+
+#endif  // AUTOMOTIVE_EVS_VTS_FRAMEHANDLER_H
diff --git a/automotive/evs/aidl/vts/FrameHandlerUltrasonics.cpp b/automotive/evs/aidl/vts/FrameHandlerUltrasonics.cpp
new file mode 100644
index 0000000..650f0ed
--- /dev/null
+++ b/automotive/evs/aidl/vts/FrameHandlerUltrasonics.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FrameHandlerUltrasonics.h"
+
+#include <aidl/android/hardware/automotive/evs/EvsEventDesc.h>
+#include <aidl/android/hardware/automotive/evs/EvsEventType.h>
+#include <aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.h>
+#include <aidl/android/hardware/automotive/evs/UltrasonicsDataFrameDesc.h>
+#include <android-base/logging.h>
+
+using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
+using ::aidl::android::hardware::automotive::evs::EvsEventType;
+using ::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray;
+using ::aidl::android::hardware::automotive::evs::UltrasonicsDataFrameDesc;
+using ::ndk::ScopedAStatus;
+
+namespace {
+
+// Struct used by SerializeWaveformData().
+struct WaveformData {
+    uint8_t receiverId;
+    std::vector<std::pair<float, float>> readings;
+};
+
+}  // namespace
+
+FrameHandlerUltrasonics::FrameHandlerUltrasonics(
+        const std::shared_ptr<IEvsUltrasonicsArray>& pArray)
+    : mEvsUltrasonicsArray(pArray), mReceiveFramesCount(0) {
+    // Nothing but member initialization
+}
+
+ScopedAStatus FrameHandlerUltrasonics::notify(const EvsEventDesc& evsEvent) {
+    switch (evsEvent.aType) {
+        case EvsEventType::STREAM_STARTED:
+        case EvsEventType::STREAM_STOPPED:
+        case EvsEventType::FRAME_DROPPED:
+        case EvsEventType::TIMEOUT:
+            mReceivedEvents.emplace_back(evsEvent);
+            break;
+        default:
+            LOG(ERROR) << "Received unexpected event";
+    }
+
+    return ScopedAStatus::ok();
+}
+
+// De-serializes shared memory to vector of WaveformData.
+// TODO(b/149950362): Add a common library for serializing and deserializing waveform data.
+std::vector<WaveformData> DeSerializeWaveformData(std::vector<uint32_t> recvReadingsCountList,
+                                                  uint8_t* pData) {
+    std::vector<WaveformData> waveformDataList(recvReadingsCountList.size());
+
+    for (int i = 0; i < waveformDataList.size(); i++) {
+        // Set Id
+        memcpy(&waveformDataList[i].receiverId, pData, sizeof(uint8_t));
+        pData += sizeof(uint8_t);
+
+        waveformDataList[i].readings.resize(recvReadingsCountList[i]);
+
+        for (auto& reading : waveformDataList[i].readings) {
+            // Set the time of flight.
+            memcpy(&reading.first, pData, sizeof(float));
+            pData += sizeof(float);
+
+            // Set the resonance.
+            memcpy(&reading.second, pData, sizeof(float));
+            pData += sizeof(float);
+        }
+    }
+    return waveformDataList;
+}
+
+bool DataFrameValidator(const UltrasonicsDataFrameDesc& /*dataFrameDesc*/) {
+    // TODO(b/214026378): implement a method to validate an ultrasonics data frame
+    (void)DeSerializeWaveformData;
+    return true;
+}
+
+ScopedAStatus FrameHandlerUltrasonics::deliverDataFrame(
+        const UltrasonicsDataFrameDesc& dataFrameDesc) {
+    LOG(DEBUG) << "FrameHandlerUltrasonics::receiveFrames";
+
+    mReceiveFramesCount++;
+
+    if (!DataFrameValidator(dataFrameDesc)) {
+        mAllFramesValid = false;
+    }
+
+    // Send done with data frame.
+    mEvsUltrasonicsArray->doneWithDataFrame(dataFrameDesc);
+    return ScopedAStatus::ok();
+}
+
+bool FrameHandlerUltrasonics::checkEventReceived(const EvsEventDesc& evsEvent) {
+    LOG(DEBUG) << "FrameHandlerUltrasonics::checkEventReceived";
+    int size = mReceivedEvents.size();  // work around
+    LOG(DEBUG) << "Received event number: " << size;
+    auto iter = find(mReceivedEvents.begin(), mReceivedEvents.end(), evsEvent);
+    return iter != mReceivedEvents.end();
+}
+
+int FrameHandlerUltrasonics::getReceiveFramesCount() {
+    return mReceiveFramesCount;
+}
+
+bool FrameHandlerUltrasonics::areAllFramesValid() {
+    return mAllFramesValid;
+}
diff --git a/automotive/evs/aidl/vts/FrameHandlerUltrasonics.h b/automotive/evs/aidl/vts/FrameHandlerUltrasonics.h
new file mode 100644
index 0000000..f853a00
--- /dev/null
+++ b/automotive/evs/aidl/vts/FrameHandlerUltrasonics.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUTOMOTIVE_EVS_VTS_FRAMEHANDLERULTRASONICS_H
+#define AUTOMOTIVE_EVS_VTS_FRAMEHANDLERULTRASONICS_H
+
+#include <aidl/android/hardware/automotive/evs/BnEvsUltrasonicsArrayStream.h>
+#include <aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.h>
+
+#include <vector>
+
+class FrameHandlerUltrasonics
+    : public ::aidl::android::hardware::automotive::evs::BnEvsUltrasonicsArrayStream {
+  public:
+    FrameHandlerUltrasonics(
+            const std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray>&
+                    pArray);
+
+    // Implementation for ::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArrayStream
+    ::ndk::ScopedAStatus notify(
+            const ::aidl::android::hardware::automotive::evs::EvsEventDesc& event) override;
+    ::ndk::ScopedAStatus deliverDataFrame(
+            const ::aidl::android::hardware::automotive::evs::UltrasonicsDataFrameDesc& desc)
+            override;
+
+    bool checkEventReceived(
+            const ::aidl::android::hardware::automotive::evs::EvsEventDesc& evsEvent);
+    int getReceiveFramesCount();
+    bool areAllFramesValid();
+
+  private:
+    std::shared_ptr<::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray>
+            mEvsUltrasonicsArray;
+    std::vector<::aidl::android::hardware::automotive::evs::EvsEventDesc> mReceivedEvents;
+    int mReceiveFramesCount;
+    bool mAllFramesValid = true;
+};
+
+#endif  // AUTOMOTIVE_EVS_VTS_FRAMEHANDLERULTRASONICS_H
diff --git a/automotive/evs/aidl/vts/OWNERS b/automotive/evs/aidl/vts/OWNERS
new file mode 100644
index 0000000..a104f50
--- /dev/null
+++ b/automotive/evs/aidl/vts/OWNERS
@@ -0,0 +1,3 @@
+#Bug component : 853002
+ankitarora@google.com
+changyeon@google.com
diff --git a/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp b/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
new file mode 100644
index 0000000..c709d40
--- /dev/null
+++ b/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
@@ -0,0 +1,2170 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "FrameHandler.h"
+#include "FrameHandlerUltrasonics.h"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/automotive/evs/BufferDesc.h>
+#include <aidl/android/hardware/automotive/evs/CameraDesc.h>
+#include <aidl/android/hardware/automotive/evs/CameraParam.h>
+#include <aidl/android/hardware/automotive/evs/DisplayDesc.h>
+#include <aidl/android/hardware/automotive/evs/DisplayState.h>
+#include <aidl/android/hardware/automotive/evs/EvsEventDesc.h>
+#include <aidl/android/hardware/automotive/evs/EvsEventType.h>
+#include <aidl/android/hardware/automotive/evs/EvsResult.h>
+#include <aidl/android/hardware/automotive/evs/IEvsCamera.h>
+#include <aidl/android/hardware/automotive/evs/IEvsDisplay.h>
+#include <aidl/android/hardware/automotive/evs/IEvsEnumerator.h>
+#include <aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.h>
+#include <aidl/android/hardware/automotive/evs/ParameterRange.h>
+#include <aidl/android/hardware/automotive/evs/Stream.h>
+#include <aidl/android/hardware/automotive/evs/UltrasonicsArrayDesc.h>
+#include <aidl/android/hardware/common/NativeHandle.h>
+#include <aidl/android/hardware/graphics/common/HardwareBufferDescription.h>
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android-base/logging.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_status.h>
+#include <system/camera_metadata.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <utils/Timers.h>
+
+#include <deque>
+#include <thread>
+#include <unordered_set>
+
+namespace {
+
+// These values are called out in the EVS design doc (as of Mar 8, 2017)
+constexpr int kMaxStreamStartMilliseconds = 500;
+constexpr int kMinimumFramesPerSecond = 10;
+constexpr int kSecondsToMilliseconds = 1000;
+constexpr int kMillisecondsToMicroseconds = 1000;
+constexpr float kNanoToMilliseconds = 0.000001f;
+constexpr float kNanoToSeconds = 0.000000001f;
+
+/*
+ * Please note that this is different from what is defined in
+ * libhardware/modules/camera/3_4/metadata/types.h; this has one additional
+ * field to store a framerate.
+ */
+typedef struct {
+    int32_t id;
+    int32_t width;
+    int32_t height;
+    int32_t format;
+    int32_t direction;
+    int32_t framerate;
+} RawStreamConfig;
+constexpr size_t kStreamCfgSz = sizeof(RawStreamConfig) / sizeof(int32_t);
+
+}  // namespace
+
+using ::aidl::android::hardware::automotive::evs::BufferDesc;
+using ::aidl::android::hardware::automotive::evs::CameraDesc;
+using ::aidl::android::hardware::automotive::evs::CameraParam;
+using ::aidl::android::hardware::automotive::evs::DisplayDesc;
+using ::aidl::android::hardware::automotive::evs::DisplayState;
+using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
+using ::aidl::android::hardware::automotive::evs::EvsEventType;
+using ::aidl::android::hardware::automotive::evs::EvsResult;
+using ::aidl::android::hardware::automotive::evs::IEvsCamera;
+using ::aidl::android::hardware::automotive::evs::IEvsDisplay;
+using ::aidl::android::hardware::automotive::evs::IEvsEnumerator;
+using ::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray;
+using ::aidl::android::hardware::automotive::evs::ParameterRange;
+using ::aidl::android::hardware::automotive::evs::Stream;
+using ::aidl::android::hardware::automotive::evs::UltrasonicsArrayDesc;
+using ::aidl::android::hardware::graphics::common::BufferUsage;
+using ::aidl::android::hardware::graphics::common::HardwareBufferDescription;
+using ::aidl::android::hardware::graphics::common::PixelFormat;
+using std::chrono_literals::operator""s;
+
+// The main test class for EVS
+class EvsAidlTest : public ::testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        // Make sure we can connect to the enumerator
+        std::string service_name = GetParam();
+        AIBinder* binder = AServiceManager_waitForService(service_name.data());
+        ASSERT_NE(binder, nullptr);
+        mEnumerator = IEvsEnumerator::fromBinder(::ndk::SpAIBinder(binder));
+        LOG(INFO) << "Test target service: " << service_name;
+
+        ASSERT_TRUE(mEnumerator->isHardware(&mIsHwModule).isOk());
+    }
+
+    virtual void TearDown() override {
+        // Attempt to close any active camera
+        for (auto&& cam : mActiveCameras) {
+            if (cam != nullptr) {
+                mEnumerator->closeCamera(cam);
+            }
+        }
+        mActiveCameras.clear();
+    }
+
+  protected:
+    void loadCameraList() {
+        // SetUp() must run first!
+        ASSERT_NE(mEnumerator, nullptr);
+
+        // Get the camera list
+        ASSERT_TRUE(mEnumerator->getCameraList(&mCameraInfo).isOk())
+                << "Failed to get a list of available cameras";
+        LOG(INFO) << "We have " << mCameraInfo.size() << " cameras.";
+    }
+
+    void loadUltrasonicsArrayList() {
+        // SetUp() must run first!
+        ASSERT_NE(mEnumerator, nullptr);
+
+        // Get the ultrasonics array list
+        ASSERT_TRUE(mEnumerator->getUltrasonicsArrayList(&mUltrasonicsArraysInfo).isOk())
+                << "Failed to get a list of available ultrasonics arrays";
+        LOG(INFO) << "We have " << mCameraInfo.size() << " ultrasonics arrays.";
+    }
+
+    bool isLogicalCamera(const camera_metadata_t* metadata) {
+        if (metadata == nullptr) {
+            // A logical camera device must have a valid camera metadata.
+            return false;
+        }
+
+        // Looking for LOGICAL_MULTI_CAMERA capability from metadata.
+        camera_metadata_ro_entry_t entry;
+        int rc = find_camera_metadata_ro_entry(metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+                                               &entry);
+        if (rc != 0) {
+            // No capabilities are found.
+            return false;
+        }
+
+        for (size_t i = 0; i < entry.count; ++i) {
+            uint8_t cap = entry.data.u8[i];
+            if (cap == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    std::unordered_set<std::string> getPhysicalCameraIds(const std::string& id, bool& flag) {
+        std::unordered_set<std::string> physicalCameras;
+        const auto it = std::find_if(mCameraInfo.begin(), mCameraInfo.end(),
+                                     [&id](const CameraDesc& desc) { return id == desc.id; });
+        if (it == mCameraInfo.end()) {
+            // Unknown camera is requested.  Return an empty list.
+            return physicalCameras;
+        }
+
+        const camera_metadata_t* metadata = reinterpret_cast<camera_metadata_t*>(&it->metadata[0]);
+        flag = isLogicalCamera(metadata);
+        if (!flag) {
+            // EVS assumes that the device w/o a valid metadata is a physical
+            // device.
+            LOG(INFO) << id << " is not a logical camera device.";
+            physicalCameras.insert(id);
+            return physicalCameras;
+        }
+
+        // Look for physical camera identifiers
+        camera_metadata_ro_entry entry;
+        int rc = find_camera_metadata_ro_entry(metadata, ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS,
+                                               &entry);
+        if (rc != 0) {
+            LOG(ERROR) << "No physical camera ID is found for a logical camera device";
+        }
+
+        const uint8_t* ids = entry.data.u8;
+        size_t start = 0;
+        for (size_t i = 0; i < entry.count; ++i) {
+            if (ids[i] == '\0') {
+                if (start != i) {
+                    std::string id(reinterpret_cast<const char*>(ids + start));
+                    physicalCameras.insert(id);
+                }
+                start = i + 1;
+            }
+        }
+
+        LOG(INFO) << id << " consists of " << physicalCameras.size() << " physical camera devices";
+        return physicalCameras;
+    }
+
+    Stream getFirstStreamConfiguration(camera_metadata_t* metadata) {
+        Stream targetCfg = {};
+        camera_metadata_entry_t streamCfgs;
+        if (!find_camera_metadata_entry(metadata, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+                                        &streamCfgs)) {
+            // Stream configurations are found in metadata
+            RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+                    targetCfg.width = ptr->width;
+                    targetCfg.height = ptr->height;
+                    targetCfg.format = static_cast<PixelFormat>(ptr->format);
+                    break;
+                }
+                ++ptr;
+            }
+        }
+
+        return targetCfg;
+    }
+
+    // Every test needs access to the service
+    std::shared_ptr<IEvsEnumerator> mEnumerator;
+    // Empty unless/util loadCameraList() is called
+    std::vector<CameraDesc> mCameraInfo;
+    // boolean to tell current module under testing is HW module implementation
+    // or not
+    bool mIsHwModule;
+    // A list of active camera handles that are need to be cleaned up
+    std::deque<std::shared_ptr<IEvsCamera>> mActiveCameras;
+    // Empty unless/util loadUltrasonicsArrayList() is called
+    std::vector<UltrasonicsArrayDesc> mUltrasonicsArraysInfo;
+    // A list of active ultrasonics array handles that are to be cleaned up
+    std::deque<std::weak_ptr<IEvsUltrasonicsArray>> mActiveUltrasonicsArrays;
+};
+
+// Test cases, their implementations, and corresponding requirements are
+// documented at go/aae-evs-public-api-test.
+
+/*
+ * CameraOpenClean:
+ * Opens each camera reported by the enumerator and then explicitly closes it via a
+ * call to closeCamera.  Then repeats the test to ensure all cameras can be reopened.
+ */
+TEST_P(EvsAidlTest, CameraOpenClean) {
+    LOG(INFO) << "Starting CameraOpenClean test";
+
+    // Get the camera list
+    loadCameraList();
+
+    // Open and close each camera twice
+    for (auto&& cam : mCameraInfo) {
+        bool isLogicalCam = false;
+        auto devices = getPhysicalCameraIds(cam.id, isLogicalCam);
+        if (mIsHwModule && isLogicalCam) {
+            LOG(INFO) << "Skip a logical device, " << cam.id << " for HW target.";
+            continue;
+        }
+
+        // Read a target resolution from the metadata
+        Stream targetCfg = getFirstStreamConfiguration(
+                reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        for (int pass = 0; pass < 2; pass++) {
+            std::shared_ptr<IEvsCamera> pCam;
+            ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+            ASSERT_NE(pCam, nullptr);
+
+            CameraDesc cameraInfo;
+            for (auto&& devName : devices) {
+                ASSERT_TRUE(pCam->getPhysicalCameraInfo(devName, &cameraInfo).isOk());
+                EXPECT_EQ(devName, cameraInfo.id);
+            }
+
+            // Store a camera handle for a clean-up
+            mActiveCameras.push_back(pCam);
+
+            // Verify that this camera self-identifies correctly
+            ASSERT_TRUE(pCam->getCameraInfo(&cameraInfo).isOk());
+            EXPECT_EQ(cam.id, cameraInfo.id);
+
+            // Verify methods for extended info
+            const auto id = 0xFFFFFFFF;  // meaningless id
+            std::vector<uint8_t> values;
+            auto status = pCam->setExtendedInfo(id, values);
+            if (isLogicalCam) {
+                EXPECT_TRUE(!status.isOk() && status.getServiceSpecificError() ==
+                                                      static_cast<int>(EvsResult::NOT_SUPPORTED));
+            } else {
+                EXPECT_TRUE(status.isOk());
+            }
+
+            status = pCam->getExtendedInfo(id, &values);
+            if (isLogicalCam) {
+                EXPECT_TRUE(!status.isOk() && status.getServiceSpecificError() ==
+                                                      static_cast<int>(EvsResult::NOT_SUPPORTED));
+            } else {
+                EXPECT_TRUE(status.isOk());
+            }
+
+            // Explicitly close the camera so resources are released right away
+            ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+            mActiveCameras.clear();
+        }
+    }
+}
+
+/*
+ * CameraOpenAggressive:
+ * Opens each camera reported by the enumerator twice in a row without an intervening closeCamera
+ * call.  This ensures that the intended "aggressive open" behavior works.  This is necessary for
+ * the system to be tolerant of shutdown/restart race conditions.
+ */
+TEST_P(EvsAidlTest, CameraOpenAggressive) {
+    LOG(INFO) << "Starting CameraOpenAggressive test";
+
+    // Get the camera list
+    loadCameraList();
+
+    // Open and close each camera twice
+    for (auto&& cam : mCameraInfo) {
+        bool isLogicalCam = false;
+        getPhysicalCameraIds(cam.id, isLogicalCam);
+        if (mIsHwModule && isLogicalCam) {
+            LOG(INFO) << "Skip a logical device, " << cam.id << " for HW target.";
+            continue;
+        }
+
+        // Read a target resolution from the metadata
+        Stream targetCfg = getFirstStreamConfiguration(
+                reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        mActiveCameras.clear();
+        std::shared_ptr<IEvsCamera> pCam;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+        EXPECT_NE(pCam, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam);
+
+        // Verify that this camera self-identifies correctly
+        CameraDesc cameraInfo;
+        ASSERT_TRUE(pCam->getCameraInfo(&cameraInfo).isOk());
+        EXPECT_EQ(cam.id, cameraInfo.id);
+
+        std::shared_ptr<IEvsCamera> pCam2;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam2).isOk());
+        EXPECT_NE(pCam2, nullptr);
+        EXPECT_NE(pCam, pCam2);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam2);
+
+        auto status = pCam->setMaxFramesInFlight(2);
+        if (mIsHwModule) {
+            // Verify that the old camera rejects calls via HW module.
+            EXPECT_TRUE(!status.isOk() && status.getServiceSpecificError() ==
+                                                  static_cast<int>(EvsResult::OWNERSHIP_LOST));
+        } else {
+            // default implementation supports multiple clients.
+            EXPECT_TRUE(status.isOk());
+        }
+
+        // Close the superseded camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+        mActiveCameras.pop_front();
+
+        // Verify that the second camera instance self-identifies correctly
+        ASSERT_TRUE(pCam2->getCameraInfo(&cameraInfo).isOk());
+        EXPECT_EQ(cam.id, cameraInfo.id);
+
+        // Close the second camera instance
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam2).isOk());
+        mActiveCameras.pop_front();
+    }
+
+    // Sleep here to ensure the destructor cleanup has time to run so we don't break follow on tests
+    sleep(1);  // I hate that this is an arbitrary time to wait.  :(  b/36122635
+}
+
+/*
+ * CameraStreamPerformance:
+ * Measure and qualify the stream start up time and streaming frame rate of each reported camera
+ */
+TEST_P(EvsAidlTest, CameraStreamPerformance) {
+    LOG(INFO) << "Starting CameraStreamPerformance test";
+
+    // Get the camera list
+    loadCameraList();
+
+    // Test each reported camera
+    for (auto&& cam : mCameraInfo) {
+        bool isLogicalCam = false;
+        auto devices = getPhysicalCameraIds(cam.id, isLogicalCam);
+        if (mIsHwModule && isLogicalCam) {
+            LOG(INFO) << "Skip a logical device " << cam.id;
+            continue;
+        }
+
+        // Read a target resolution from the metadata
+        Stream targetCfg = getFirstStreamConfiguration(
+                reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        std::shared_ptr<IEvsCamera> pCam;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+        EXPECT_NE(pCam, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam);
+
+        // Set up a frame receiver object which will fire up its own thread
+        std::shared_ptr<FrameHandler> frameHandler =
+                std::make_shared<FrameHandler>(pCam, cam, nullptr, FrameHandler::eAutoReturn);
+        EXPECT_NE(frameHandler, nullptr);
+
+        // Start the camera's video stream
+        nsecs_t start = systemTime(SYSTEM_TIME_MONOTONIC);
+        ASSERT_TRUE(frameHandler->startStream());
+
+        // Ensure the first frame arrived within the expected time
+        frameHandler->waitForFrameCount(1);
+        nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC);
+        nsecs_t timeToFirstFrame = systemTime(SYSTEM_TIME_MONOTONIC) - start;
+
+        // Extra delays are expected when we attempt to start a video stream on
+        // the logical camera device.  The amount of delay is expected the
+        // number of physical camera devices multiplied by
+        // kMaxStreamStartMilliseconds at most.
+        EXPECT_LE(nanoseconds_to_milliseconds(timeToFirstFrame),
+                  kMaxStreamStartMilliseconds * devices.size());
+        printf("%s: Measured time to first frame %0.2f ms\n", cam.id.data(),
+               timeToFirstFrame * kNanoToMilliseconds);
+        LOG(INFO) << cam.id << ": Measured time to first frame " << 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);
+
+        // Even when the camera pointer goes out of scope, the FrameHandler object will
+        // keep the stream alive unless we tell it to shutdown.
+        // Also note that the FrameHandle and the Camera have a mutual circular reference, so
+        // we have to break that cycle in order for either of them to get cleaned up.
+        frameHandler->shutdown();
+
+        unsigned framesReceived = 0;
+        frameHandler->getFramesCounters(&framesReceived, nullptr);
+        framesReceived = framesReceived - 1;  // Back out the first frame we already waited for
+        nsecs_t runTime = end - firstFrame;
+        float framesPerSecond = framesReceived / (runTime * kNanoToSeconds);
+        printf("Measured camera rate %3.2f fps\n", framesPerSecond);
+        LOG(INFO) << "Measured camera rate " << std::scientific << framesPerSecond << " fps.";
+        EXPECT_GE(framesPerSecond, kMinimumFramesPerSecond);
+
+        // Explicitly release the camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+        mActiveCameras.clear();
+    }
+}
+
+/*
+ * CameraStreamBuffering:
+ * Ensure the camera implementation behaves properly when the client holds onto buffers for more
+ * than one frame time.  The camera must cleanly skip frames until the client is ready again.
+ */
+TEST_P(EvsAidlTest, CameraStreamBuffering) {
+    LOG(INFO) << "Starting CameraStreamBuffering test";
+
+    // Arbitrary constant (should be > 1 and not too big)
+    static const unsigned int kBuffersToHold = 6;
+
+    // Get the camera list
+    loadCameraList();
+
+    // Test each reported camera
+    for (auto&& cam : mCameraInfo) {
+        bool isLogicalCam = false;
+        getPhysicalCameraIds(cam.id, isLogicalCam);
+        if (mIsHwModule && isLogicalCam) {
+            LOG(INFO) << "Skip a logical device " << cam.id << " for HW target.";
+            continue;
+        }
+
+        // Read a target resolution from the metadata
+        Stream targetCfg = getFirstStreamConfiguration(
+                reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        std::shared_ptr<IEvsCamera> pCam;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+        EXPECT_NE(pCam, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam);
+
+        // Ask for a very large number of buffers in flight to ensure it errors correctly
+        auto badResult = pCam->setMaxFramesInFlight(0xFFFFFFFF);
+        EXPECT_TRUE(!badResult.isOk() && badResult.getServiceSpecificError() ==
+                                                 static_cast<int>(EvsResult::BUFFER_NOT_AVAILABLE));
+
+        // Now ask for exactly two buffers in flight as we'll test behavior in that case
+        ASSERT_TRUE(pCam->setMaxFramesInFlight(kBuffersToHold).isOk());
+
+        // Set up a frame receiver object which will fire up its own thread.
+        std::shared_ptr<FrameHandler> frameHandler =
+                std::make_shared<FrameHandler>(pCam, cam, nullptr, FrameHandler::eNoAutoReturn);
+        EXPECT_NE(frameHandler, nullptr);
+
+        // Start the camera's video stream
+        ASSERT_TRUE(frameHandler->startStream());
+
+        // Check that the video stream stalls once we've gotten exactly the number of buffers
+        // we requested since we told the frameHandler not to return them.
+        sleep(1);  // 1 second should be enough for at least 5 frames to be delivered worst case
+        unsigned framesReceived = 0;
+        frameHandler->getFramesCounters(&framesReceived, nullptr);
+        ASSERT_EQ(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
+
+        // Give back one buffer
+        ASSERT_TRUE(frameHandler->returnHeldBuffer());
+
+        // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
+        // filled since we require 10fps minimum -- but give a 10% allowance just in case.
+        usleep(110 * kMillisecondsToMicroseconds);
+        frameHandler->getFramesCounters(&framesReceived, nullptr);
+        EXPECT_EQ(kBuffersToHold + 1, framesReceived) << "Stream should've resumed";
+
+        // Even when the camera pointer goes out of scope, the FrameHandler object will
+        // keep the stream alive unless we tell it to shutdown.
+        // Also note that the FrameHandle and the Camera have a mutual circular reference, so
+        // we have to break that cycle in order for either of them to get cleaned up.
+        frameHandler->shutdown();
+
+        // Explicitly release the camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+        mActiveCameras.clear();
+    }
+}
+
+/*
+ * CameraToDisplayRoundTrip:
+ * End to end test of data flowing from the camera to the display.  Each delivered frame of camera
+ * imagery is simply copied to the display buffer and presented on screen.  This is the one test
+ * which a human could observe to see the operation of the system on the physical display.
+ */
+TEST_P(EvsAidlTest, CameraToDisplayRoundTrip) {
+    LOG(INFO) << "Starting CameraToDisplayRoundTrip test";
+
+    // Get the camera list
+    loadCameraList();
+
+    // Request available display IDs
+    uint8_t targetDisplayId = 0;
+    std::vector<uint8_t> displayIds;
+    ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
+    EXPECT_GT(displayIds.size(), 0);
+    targetDisplayId = displayIds[0];
+
+    // Request exclusive access to the first EVS display
+    std::shared_ptr<IEvsDisplay> pDisplay;
+    ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
+    EXPECT_NE(pDisplay, nullptr);
+    LOG(INFO) << "Display " << targetDisplayId << " is in use.";
+
+    // Get the display descriptor
+    DisplayDesc displayDesc;
+    ASSERT_TRUE(pDisplay->getDisplayInfo(&displayDesc).isOk());
+    LOG(INFO) << "    Resolution: " << displayDesc.width << "x" << displayDesc.height;
+    ASSERT_GT(displayDesc.width, 0);
+    ASSERT_GT(displayDesc.height, 0);
+
+    // Test each reported camera
+    for (auto&& cam : mCameraInfo) {
+        bool isLogicalCam = false;
+        getPhysicalCameraIds(cam.id, isLogicalCam);
+        if (mIsHwModule && isLogicalCam) {
+            LOG(INFO) << "Skip a logical device " << cam.id << " for HW target.";
+            continue;
+        }
+
+        // Read a target resolution from the metadata
+        Stream targetCfg = getFirstStreamConfiguration(
+                reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        std::shared_ptr<IEvsCamera> pCam;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+        EXPECT_NE(pCam, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam);
+
+        // Set up a frame receiver object which will fire up its own thread.
+        std::shared_ptr<FrameHandler> frameHandler =
+                std::make_shared<FrameHandler>(pCam, cam, pDisplay, FrameHandler::eAutoReturn);
+        EXPECT_NE(frameHandler, nullptr);
+
+        // Activate the display
+        ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME).isOk());
+
+        // Start the camera's video stream
+        ASSERT_TRUE(frameHandler->startStream());
+
+        // Wait a while to let the data flow
+        static const int kSecondsToWait = 5;
+        const int streamTimeMs =
+                kSecondsToWait * kSecondsToMilliseconds - kMaxStreamStartMilliseconds;
+        const unsigned minimumFramesExpected =
+                streamTimeMs * kMinimumFramesPerSecond / kSecondsToMilliseconds;
+        sleep(kSecondsToWait);
+        unsigned framesReceived = 0;
+        unsigned framesDisplayed = 0;
+        frameHandler->getFramesCounters(&framesReceived, &framesDisplayed);
+        EXPECT_EQ(framesReceived, framesDisplayed);
+        EXPECT_GE(framesDisplayed, minimumFramesExpected);
+
+        // Turn off the display (yes, before the stream stops -- it should be handled)
+        ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::NOT_VISIBLE).isOk());
+
+        // Shut down the streamer
+        frameHandler->shutdown();
+
+        // Explicitly release the camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+        mActiveCameras.clear();
+    }
+
+    // Explicitly release the display
+    ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+}
+
+/*
+ * MultiCameraStream:
+ * Verify that each client can start and stop video streams on the same
+ * underlying camera.
+ */
+TEST_P(EvsAidlTest, MultiCameraStream) {
+    LOG(INFO) << "Starting MultiCameraStream test";
+
+    if (mIsHwModule) {
+        // This test is not for HW module implementation.
+        return;
+    }
+
+    // Get the camera list
+    loadCameraList();
+
+    // Test each reported camera
+    for (auto&& cam : mCameraInfo) {
+        // Read a target resolution from the metadata
+        Stream targetCfg = getFirstStreamConfiguration(
+                reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        // Create two camera clients.
+        std::shared_ptr<IEvsCamera> pCam0;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam0).isOk());
+        EXPECT_NE(pCam0, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam0);
+
+        std::shared_ptr<IEvsCamera> pCam1;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
+        EXPECT_NE(pCam1, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam1);
+
+        // Set up per-client frame receiver objects which will fire up its own thread
+        std::shared_ptr<FrameHandler> frameHandler0 =
+                std::make_shared<FrameHandler>(pCam0, cam, nullptr, FrameHandler::eAutoReturn);
+        std::shared_ptr<FrameHandler> frameHandler1 =
+                std::make_shared<FrameHandler>(pCam1, cam, nullptr, FrameHandler::eAutoReturn);
+        EXPECT_NE(frameHandler0, nullptr);
+        EXPECT_NE(frameHandler1, nullptr);
+
+        // Start the camera's video stream via client 0
+        ASSERT_TRUE(frameHandler0->startStream());
+        ASSERT_TRUE(frameHandler1->startStream());
+
+        // Ensure the stream starts
+        frameHandler0->waitForFrameCount(1);
+        frameHandler1->waitForFrameCount(1);
+
+        nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC);
+
+        // Wait a bit, then ensure both clients get at least the required minimum number of frames
+        sleep(5);
+        nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
+        unsigned framesReceived0 = 0, framesReceived1 = 0;
+        frameHandler0->getFramesCounters(&framesReceived0, nullptr);
+        frameHandler1->getFramesCounters(&framesReceived1, nullptr);
+        framesReceived0 = framesReceived0 - 1;  // Back out the first frame we already waited for
+        framesReceived1 = framesReceived1 - 1;  // Back out the first frame we already waited for
+        nsecs_t runTime = end - firstFrame;
+        float framesPerSecond0 = framesReceived0 / (runTime * kNanoToSeconds);
+        float framesPerSecond1 = framesReceived1 / (runTime * kNanoToSeconds);
+        LOG(INFO) << "Measured camera rate " << std::scientific << framesPerSecond0 << " fps and "
+                  << framesPerSecond1 << " fps";
+        EXPECT_GE(framesPerSecond0, kMinimumFramesPerSecond);
+        EXPECT_GE(framesPerSecond1, kMinimumFramesPerSecond);
+
+        // Shutdown one client
+        frameHandler0->shutdown();
+
+        // Read frame counters again
+        frameHandler0->getFramesCounters(&framesReceived0, nullptr);
+        frameHandler1->getFramesCounters(&framesReceived1, nullptr);
+
+        // Wait a bit again
+        sleep(5);
+        unsigned framesReceivedAfterStop0 = 0, framesReceivedAfterStop1 = 0;
+        frameHandler0->getFramesCounters(&framesReceivedAfterStop0, nullptr);
+        frameHandler1->getFramesCounters(&framesReceivedAfterStop1, nullptr);
+        EXPECT_EQ(framesReceived0, framesReceivedAfterStop0);
+        EXPECT_LT(framesReceived1, framesReceivedAfterStop1);
+
+        // Shutdown another
+        frameHandler1->shutdown();
+
+        // Explicitly release the camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam0).isOk());
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam1).isOk());
+        mActiveCameras.clear();
+
+        // TODO(b/145459970, b/145457727): below sleep() is added to ensure the
+        // destruction of active camera objects; this may be related with two
+        // issues.
+        sleep(1);
+    }
+}
+
+/*
+ * CameraParameter:
+ * Verify that a client can adjust a camera parameter.
+ */
+TEST_P(EvsAidlTest, CameraParameter) {
+    LOG(INFO) << "Starting CameraParameter test";
+
+    // Get the camera list
+    loadCameraList();
+
+    // Test each reported camera
+    for (auto&& cam : mCameraInfo) {
+        bool isLogicalCam = false;
+        getPhysicalCameraIds(cam.id, isLogicalCam);
+        if (isLogicalCam) {
+            // TODO(b/145465724): Support camera parameter programming on
+            // logical devices.
+            LOG(INFO) << "Skip a logical device " << cam.id;
+            continue;
+        }
+
+        // Read a target resolution from the metadata
+        Stream targetCfg = getFirstStreamConfiguration(
+                reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        // Create a camera client
+        std::shared_ptr<IEvsCamera> pCam;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+        EXPECT_NE(pCam, nullptr);
+
+        // Store a camera
+        mActiveCameras.push_back(pCam);
+
+        // Get the parameter list
+        std::vector<CameraParam> cmds;
+        ASSERT_TRUE(pCam->getParameterList(&cmds).isOk());
+        if (cmds.size() < 1) {
+            continue;
+        }
+
+        // Set up per-client frame receiver objects which will fire up its own thread
+        std::shared_ptr<FrameHandler> frameHandler =
+                std::make_shared<FrameHandler>(pCam, cam, nullptr, FrameHandler::eAutoReturn);
+        EXPECT_NE(frameHandler, nullptr);
+
+        // Start the camera's video stream
+        ASSERT_TRUE(frameHandler->startStream());
+
+        // Ensure the stream starts
+        frameHandler->waitForFrameCount(1);
+
+        // Set current client is the primary client
+        ASSERT_TRUE(pCam->setPrimaryClient().isOk());
+        for (auto& cmd : cmds) {
+            // Get a valid parameter value range
+            ParameterRange range;
+            ASSERT_TRUE(pCam->getIntParameterRange(cmd, &range).isOk());
+
+            std::vector<int32_t> values;
+            if (cmd == CameraParam::ABSOLUTE_FOCUS) {
+                // Try to turn off auto-focus
+                ASSERT_TRUE(pCam->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
+                for (auto&& v : values) {
+                    EXPECT_EQ(v, 0);
+                }
+            }
+
+            // Try to program a parameter with a random value [minVal, maxVal]
+            int32_t val0 = range.min + (std::rand() % (range.max - range.min));
+
+            // Rounding down
+            val0 = val0 - (val0 % range.step);
+            values.clear();
+            ASSERT_TRUE(pCam->setIntParameter(cmd, val0, &values).isOk());
+
+            values.clear();
+            ASSERT_TRUE(pCam->getIntParameter(cmd, &values).isOk());
+            for (auto&& v : values) {
+                EXPECT_EQ(val0, v) << "Values are not matched.";
+            }
+        }
+        ASSERT_TRUE(pCam->unsetPrimaryClient().isOk());
+
+        // Shutdown
+        frameHandler->shutdown();
+
+        // Explicitly release the camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+        mActiveCameras.clear();
+    }
+}
+
+/*
+ * CameraPrimaryClientRelease
+ * Verify that non-primary client gets notified when the primary client either
+ * terminates or releases a role.
+ */
+TEST_P(EvsAidlTest, CameraPrimaryClientRelease) {
+    LOG(INFO) << "Starting CameraPrimaryClientRelease test";
+
+    if (mIsHwModule) {
+        // This test is not for HW module implementation.
+        return;
+    }
+
+    // Get the camera list
+    loadCameraList();
+
+    // Test each reported camera
+    for (auto&& cam : mCameraInfo) {
+        bool isLogicalCam = false;
+        getPhysicalCameraIds(cam.id, isLogicalCam);
+        if (isLogicalCam) {
+            // TODO(b/145465724): Support camera parameter programming on
+            // logical devices.
+            LOG(INFO) << "Skip a logical device " << cam.id;
+            continue;
+        }
+
+        // Read a target resolution from the metadata
+        Stream targetCfg = getFirstStreamConfiguration(
+                reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        // Create two camera clients.
+        std::shared_ptr<IEvsCamera> pPrimaryCam;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pPrimaryCam).isOk());
+        EXPECT_NE(pPrimaryCam, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pPrimaryCam);
+
+        std::shared_ptr<IEvsCamera> pSecondaryCam;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pSecondaryCam).isOk());
+        EXPECT_NE(pSecondaryCam, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pSecondaryCam);
+
+        // Set up per-client frame receiver objects which will fire up its own thread
+        std::shared_ptr<FrameHandler> frameHandlerPrimary = std::make_shared<FrameHandler>(
+                pPrimaryCam, cam, nullptr, FrameHandler::eAutoReturn);
+        std::shared_ptr<FrameHandler> frameHandlerSecondary = std::make_shared<FrameHandler>(
+                pSecondaryCam, cam, nullptr, FrameHandler::eAutoReturn);
+        EXPECT_NE(frameHandlerPrimary, nullptr);
+        EXPECT_NE(frameHandlerSecondary, nullptr);
+
+        // Set one client as the primary client
+        ASSERT_TRUE(pPrimaryCam->setPrimaryClient().isOk());
+
+        // Try to set another client as the primary client.
+        ASSERT_FALSE(pSecondaryCam->setPrimaryClient().isOk());
+
+        // Start the camera's video stream via a primary client client.
+        ASSERT_TRUE(frameHandlerPrimary->startStream());
+
+        // Ensure the stream starts
+        frameHandlerPrimary->waitForFrameCount(1);
+
+        // Start the camera's video stream via another client
+        ASSERT_TRUE(frameHandlerSecondary->startStream());
+
+        // Ensure the stream starts
+        frameHandlerSecondary->waitForFrameCount(1);
+
+        // Non-primary client expects to receive a primary client role relesed
+        // notification.
+        EvsEventDesc aTargetEvent = {};
+        EvsEventDesc aNotification = {};
+
+        bool listening = false;
+        std::mutex eventLock;
+        std::condition_variable eventCond;
+        std::thread listener =
+                std::thread([&aNotification, &frameHandlerSecondary, &listening, &eventCond]() {
+                    // Notify that a listening thread is running.
+                    listening = true;
+                    eventCond.notify_all();
+
+                    EvsEventDesc aTargetEvent;
+                    aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
+                    if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification, true)) {
+                        LOG(WARNING) << "A timer is expired before a target event is fired.";
+                    }
+                });
+
+        // Wait until a listening thread starts.
+        std::unique_lock<std::mutex> lock(eventLock);
+        auto timer = std::chrono::system_clock::now();
+        while (!listening) {
+            timer += 1s;
+            eventCond.wait_until(lock, timer);
+        }
+        lock.unlock();
+
+        // Release a primary client role.
+        ASSERT_TRUE(pPrimaryCam->unsetPrimaryClient().isOk());
+
+        // Join a listening thread.
+        if (listener.joinable()) {
+            listener.join();
+        }
+
+        // Verify change notifications.
+        ASSERT_EQ(EvsEventType::MASTER_RELEASED, static_cast<EvsEventType>(aNotification.aType));
+
+        // Non-primary becomes a primary client.
+        ASSERT_TRUE(pSecondaryCam->setPrimaryClient().isOk());
+
+        // Previous primary client fails to become a primary client.
+        ASSERT_FALSE(pPrimaryCam->setPrimaryClient().isOk());
+
+        listening = false;
+        listener = std::thread([&aNotification, &frameHandlerPrimary, &listening, &eventCond]() {
+            // Notify that a listening thread is running.
+            listening = true;
+            eventCond.notify_all();
+
+            EvsEventDesc aTargetEvent;
+            aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
+            if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification, true)) {
+                LOG(WARNING) << "A timer is expired before a target event is fired.";
+            }
+        });
+
+        // Wait until a listening thread starts.
+        timer = std::chrono::system_clock::now();
+        lock.lock();
+        while (!listening) {
+            eventCond.wait_until(lock, timer + 1s);
+        }
+        lock.unlock();
+
+        // Closing current primary client.
+        frameHandlerSecondary->shutdown();
+
+        // Join a listening thread.
+        if (listener.joinable()) {
+            listener.join();
+        }
+
+        // Verify change notifications.
+        ASSERT_EQ(EvsEventType::MASTER_RELEASED, static_cast<EvsEventType>(aNotification.aType));
+
+        // Closing streams.
+        frameHandlerPrimary->shutdown();
+
+        // Explicitly release the camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pPrimaryCam).isOk());
+        ASSERT_TRUE(mEnumerator->closeCamera(pSecondaryCam).isOk());
+        mActiveCameras.clear();
+    }
+}
+
+/*
+ * MultiCameraParameter:
+ * Verify that primary and non-primary clients behave as expected when they try to adjust
+ * camera parameters.
+ */
+TEST_P(EvsAidlTest, MultiCameraParameter) {
+    LOG(INFO) << "Starting MultiCameraParameter test";
+
+    if (mIsHwModule) {
+        // This test is not for HW module implementation.
+        return;
+    }
+
+    // Get the camera list
+    loadCameraList();
+
+    // Test each reported camera
+    for (auto&& cam : mCameraInfo) {
+        bool isLogicalCam = false;
+        getPhysicalCameraIds(cam.id, isLogicalCam);
+        if (isLogicalCam) {
+            // TODO(b/145465724): Support camera parameter programming on
+            // logical devices.
+            LOG(INFO) << "Skip a logical device " << cam.id;
+            continue;
+        }
+
+        // Read a target resolution from the metadata
+        Stream targetCfg = getFirstStreamConfiguration(
+                reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        // Create two camera clients.
+        std::shared_ptr<IEvsCamera> pPrimaryCam;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pPrimaryCam).isOk());
+        EXPECT_NE(pPrimaryCam, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pPrimaryCam);
+
+        std::shared_ptr<IEvsCamera> pSecondaryCam;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pSecondaryCam).isOk());
+        EXPECT_NE(pSecondaryCam, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pSecondaryCam);
+
+        // Get the parameter list
+        std::vector<CameraParam> camPrimaryCmds, camSecondaryCmds;
+        ASSERT_TRUE(pPrimaryCam->getParameterList(&camPrimaryCmds).isOk());
+        ASSERT_TRUE(pSecondaryCam->getParameterList(&camSecondaryCmds).isOk());
+        if (camPrimaryCmds.size() < 1 || camSecondaryCmds.size() < 1) {
+            // Skip a camera device if it does not support any parameter.
+            continue;
+        }
+
+        // Set up per-client frame receiver objects which will fire up its own thread
+        std::shared_ptr<FrameHandler> frameHandlerPrimary = std::make_shared<FrameHandler>(
+                pPrimaryCam, cam, nullptr, FrameHandler::eAutoReturn);
+        std::shared_ptr<FrameHandler> frameHandlerSecondary = std::make_shared<FrameHandler>(
+                pSecondaryCam, cam, nullptr, FrameHandler::eAutoReturn);
+        EXPECT_NE(frameHandlerPrimary, nullptr);
+        EXPECT_NE(frameHandlerSecondary, nullptr);
+
+        // Set one client as the primary client.
+        ASSERT_TRUE(pPrimaryCam->setPrimaryClient().isOk());
+
+        // Try to set another client as the primary client.
+        ASSERT_FALSE(pSecondaryCam->setPrimaryClient().isOk());
+
+        // Start the camera's video stream via a primary client client.
+        ASSERT_TRUE(frameHandlerPrimary->startStream());
+
+        // Ensure the stream starts
+        frameHandlerPrimary->waitForFrameCount(1);
+
+        // Start the camera's video stream via another client
+        ASSERT_TRUE(frameHandlerSecondary->startStream());
+
+        // Ensure the stream starts
+        frameHandlerSecondary->waitForFrameCount(1);
+
+        int32_t val0 = 0;
+        std::vector<int32_t> values;
+        EvsEventDesc aNotification0 = {};
+        EvsEventDesc aNotification1 = {};
+        for (auto& cmd : camPrimaryCmds) {
+            // Get a valid parameter value range
+            ParameterRange range;
+            ASSERT_TRUE(pPrimaryCam->getIntParameterRange(cmd, &range).isOk());
+            if (cmd == CameraParam::ABSOLUTE_FOCUS) {
+                // Try to turn off auto-focus
+                values.clear();
+                ASSERT_TRUE(
+                        pPrimaryCam->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
+                for (auto&& v : values) {
+                    EXPECT_EQ(v, 0);
+                }
+            }
+
+            // Calculate a parameter value to program.
+            val0 = range.min + (std::rand() % (range.max - range.min));
+            val0 = val0 - (val0 % range.step);
+
+            // Prepare and start event listeners.
+            bool listening0 = false;
+            bool listening1 = false;
+            std::condition_variable eventCond;
+            std::thread listener0 = std::thread([cmd, val0, &aNotification0, &frameHandlerPrimary,
+                                                 &listening0, &listening1, &eventCond]() {
+                listening0 = true;
+                if (listening1) {
+                    eventCond.notify_all();
+                }
+
+                EvsEventDesc aTargetEvent;
+                aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+                aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
+                aTargetEvent.payload[1] = val0;
+                if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification0)) {
+                    LOG(WARNING) << "A timer is expired before a target event is fired.";
+                }
+            });
+            std::thread listener1 = std::thread([cmd, val0, &aNotification1, &frameHandlerSecondary,
+                                                 &listening0, &listening1, &eventCond]() {
+                listening1 = true;
+                if (listening0) {
+                    eventCond.notify_all();
+                }
+
+                EvsEventDesc aTargetEvent;
+                aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+                aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
+                aTargetEvent.payload[1] = val0;
+                if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification1)) {
+                    LOG(WARNING) << "A timer is expired before a target event is fired.";
+                }
+            });
+
+            // Wait until a listening thread starts.
+            std::mutex eventLock;
+            std::unique_lock<std::mutex> lock(eventLock);
+            auto timer = std::chrono::system_clock::now();
+            while (!listening0 || !listening1) {
+                eventCond.wait_until(lock, timer + 1s);
+            }
+            lock.unlock();
+
+            // Try to program a parameter
+            values.clear();
+            ASSERT_TRUE(pPrimaryCam->setIntParameter(cmd, val0, &values).isOk());
+            for (auto&& v : values) {
+                EXPECT_EQ(val0, v) << "Values are not matched.";
+            }
+
+            // Join a listening thread.
+            if (listener0.joinable()) {
+                listener0.join();
+            }
+            if (listener1.joinable()) {
+                listener1.join();
+            }
+
+            // Verify a change notification
+            ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
+                      static_cast<EvsEventType>(aNotification0.aType));
+            ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
+                      static_cast<EvsEventType>(aNotification1.aType));
+            ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification0.payload[0]));
+            ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification1.payload[0]));
+            for (auto&& v : values) {
+                ASSERT_EQ(v, static_cast<int32_t>(aNotification0.payload[1]));
+                ASSERT_EQ(v, static_cast<int32_t>(aNotification1.payload[1]));
+            }
+
+            // Clients expects to receive a parameter change notification
+            // whenever a primary client client adjusts it.
+            values.clear();
+            ASSERT_TRUE(pPrimaryCam->getIntParameter(cmd, &values).isOk());
+            for (auto&& v : values) {
+                EXPECT_EQ(val0, v) << "Values are not matched.";
+            }
+        }
+
+        // Try to adjust a parameter via non-primary client
+        values.clear();
+        ASSERT_FALSE(pSecondaryCam->setIntParameter(camSecondaryCmds[0], val0, &values).isOk());
+
+        // Non-primary client attempts to be a primary client
+        ASSERT_FALSE(pSecondaryCam->setPrimaryClient().isOk());
+
+        // Primary client retires from a primary client role
+        bool listening = false;
+        std::condition_variable eventCond;
+        std::thread listener =
+                std::thread([&aNotification0, &frameHandlerSecondary, &listening, &eventCond]() {
+                    listening = true;
+                    eventCond.notify_all();
+
+                    EvsEventDesc aTargetEvent;
+                    aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
+                    if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification0, true)) {
+                        LOG(WARNING) << "A timer is expired before a target event is fired.";
+                    }
+                });
+
+        std::mutex eventLock;
+        auto timer = std::chrono::system_clock::now();
+        std::unique_lock<std::mutex> lock(eventLock);
+        while (!listening) {
+            eventCond.wait_until(lock, timer + 1s);
+        }
+        lock.unlock();
+
+        ASSERT_TRUE(pPrimaryCam->unsetPrimaryClient().isOk());
+
+        if (listener.joinable()) {
+            listener.join();
+        }
+        ASSERT_EQ(EvsEventType::MASTER_RELEASED, static_cast<EvsEventType>(aNotification0.aType));
+
+        // Try to adjust a parameter after being retired
+        values.clear();
+        ASSERT_FALSE(pPrimaryCam->setIntParameter(camPrimaryCmds[0], val0, &values).isOk());
+
+        // Non-primary client becomes a primary client
+        ASSERT_TRUE(pSecondaryCam->setPrimaryClient().isOk());
+
+        // Try to adjust a parameter via new primary client
+        for (auto& cmd : camSecondaryCmds) {
+            // Get a valid parameter value range
+            ParameterRange range;
+            ASSERT_TRUE(pSecondaryCam->getIntParameterRange(cmd, &range).isOk());
+
+            values.clear();
+            if (cmd == CameraParam::ABSOLUTE_FOCUS) {
+                // Try to turn off auto-focus
+                values.clear();
+                ASSERT_TRUE(
+                        pSecondaryCam->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
+                for (auto&& v : values) {
+                    EXPECT_EQ(v, 0);
+                }
+            }
+
+            // Calculate a parameter value to program.  This is being rounding down.
+            val0 = range.min + (std::rand() % (range.max - range.min));
+            val0 = val0 - (val0 % range.step);
+
+            // Prepare and start event listeners.
+            bool listening0 = false;
+            bool listening1 = false;
+            std::condition_variable eventCond;
+            std::thread listener0 = std::thread([&]() {
+                listening0 = true;
+                if (listening1) {
+                    eventCond.notify_all();
+                }
+
+                EvsEventDesc aTargetEvent;
+                aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+                aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
+                aTargetEvent.payload[1] = val0;
+                if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification0)) {
+                    LOG(WARNING) << "A timer is expired before a target event is fired.";
+                }
+            });
+            std::thread listener1 = std::thread([&]() {
+                listening1 = true;
+                if (listening0) {
+                    eventCond.notify_all();
+                }
+
+                EvsEventDesc aTargetEvent;
+                aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+                aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
+                aTargetEvent.payload[1] = val0;
+                if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification1)) {
+                    LOG(WARNING) << "A timer is expired before a target event is fired.";
+                }
+            });
+
+            // Wait until a listening thread starts.
+            std::mutex eventLock;
+            std::unique_lock<std::mutex> lock(eventLock);
+            auto timer = std::chrono::system_clock::now();
+            while (!listening0 || !listening1) {
+                eventCond.wait_until(lock, timer + 1s);
+            }
+            lock.unlock();
+
+            // Try to program a parameter
+            values.clear();
+            ASSERT_TRUE(pSecondaryCam->setIntParameter(cmd, val0, &values).isOk());
+
+            // Clients expects to receive a parameter change notification
+            // whenever a primary client client adjusts it.
+            values.clear();
+            ASSERT_TRUE(pSecondaryCam->getIntParameter(cmd, &values).isOk());
+            for (auto&& v : values) {
+                EXPECT_EQ(val0, v) << "Values are not matched.";
+            }
+
+            // Join a listening thread.
+            if (listener0.joinable()) {
+                listener0.join();
+            }
+            if (listener1.joinable()) {
+                listener1.join();
+            }
+
+            // Verify a change notification
+            ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
+                      static_cast<EvsEventType>(aNotification0.aType));
+            ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
+                      static_cast<EvsEventType>(aNotification1.aType));
+            ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification0.payload[0]));
+            ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification1.payload[0]));
+            for (auto&& v : values) {
+                ASSERT_EQ(v, static_cast<int32_t>(aNotification0.payload[1]));
+                ASSERT_EQ(v, static_cast<int32_t>(aNotification1.payload[1]));
+            }
+        }
+
+        // New primary client retires from the role
+        ASSERT_TRUE(pSecondaryCam->unsetPrimaryClient().isOk());
+
+        // Shutdown
+        frameHandlerPrimary->shutdown();
+        frameHandlerSecondary->shutdown();
+
+        // Explicitly release the camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pPrimaryCam).isOk());
+        ASSERT_TRUE(mEnumerator->closeCamera(pSecondaryCam).isOk());
+        mActiveCameras.clear();
+    }
+}
+
+/*
+ * HighPriorityCameraClient:
+ * EVS client, which owns the display, is priortized and therefore can take over
+ * a primary client role from other EVS clients without the display.
+ */
+TEST_P(EvsAidlTest, HighPriorityCameraClient) {
+    LOG(INFO) << "Starting HighPriorityCameraClient test";
+
+    if (mIsHwModule) {
+        // This test is not for HW module implementation.
+        return;
+    }
+
+    // Get the camera list
+    loadCameraList();
+
+    // Request available display IDs
+    uint8_t targetDisplayId = 0;
+    std::vector<uint8_t> displayIds;
+    ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
+    EXPECT_GT(displayIds.size(), 0);
+    targetDisplayId = displayIds[0];
+
+    // Request exclusive access to the EVS display
+    std::shared_ptr<IEvsDisplay> pDisplay;
+    ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
+    EXPECT_NE(pDisplay, nullptr);
+
+    // Test each reported camera
+    for (auto&& cam : mCameraInfo) {
+        // Read a target resolution from the metadata
+        Stream targetCfg = getFirstStreamConfiguration(
+                reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        // Create two clients
+        std::shared_ptr<IEvsCamera> pCam0;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam0).isOk());
+        EXPECT_NE(pCam0, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam0);
+
+        std::shared_ptr<IEvsCamera> pCam1;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
+        EXPECT_NE(pCam1, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam1);
+
+        // Get the parameter list; this test will use the first command in both
+        // lists.
+        std::vector<CameraParam> cam0Cmds, cam1Cmds;
+        ASSERT_TRUE(pCam0->getParameterList(&cam0Cmds).isOk());
+        ASSERT_TRUE(pCam1->getParameterList(&cam1Cmds).isOk());
+        if (cam0Cmds.size() < 1 || cam1Cmds.size() < 1) {
+            // Cannot execute this test.
+            return;
+        }
+
+        // Set up a frame receiver object which will fire up its own thread.
+        std::shared_ptr<FrameHandler> frameHandler0 =
+                std::make_shared<FrameHandler>(pCam0, cam, nullptr, FrameHandler::eAutoReturn);
+        std::shared_ptr<FrameHandler> frameHandler1 =
+                std::make_shared<FrameHandler>(pCam1, cam, nullptr, FrameHandler::eAutoReturn);
+        EXPECT_NE(frameHandler0, nullptr);
+        EXPECT_NE(frameHandler1, nullptr);
+
+        // Activate the display
+        ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME).isOk());
+
+        // Start the camera's video stream
+        ASSERT_TRUE(frameHandler0->startStream());
+        ASSERT_TRUE(frameHandler1->startStream());
+
+        // Ensure the stream starts
+        frameHandler0->waitForFrameCount(1);
+        frameHandler1->waitForFrameCount(1);
+
+        // Client 1 becomes a primary client and programs a parameter.
+
+        // Get a valid parameter value range
+        ParameterRange range;
+        ASSERT_TRUE(pCam1->getIntParameterRange(cam1Cmds[0], &range).isOk());
+
+        // Client1 becomes a primary client
+        ASSERT_TRUE(pCam1->setPrimaryClient().isOk());
+
+        std::vector<int32_t> values;
+        EvsEventDesc aTargetEvent = {};
+        EvsEventDesc aNotification = {};
+        bool listening = false;
+        std::mutex eventLock;
+        std::condition_variable eventCond;
+        if (cam1Cmds[0] == CameraParam::ABSOLUTE_FOCUS) {
+            std::thread listener =
+                    std::thread([&frameHandler0, &aNotification, &listening, &eventCond] {
+                        listening = true;
+                        eventCond.notify_all();
+
+                        EvsEventDesc aTargetEvent;
+                        aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+                        aTargetEvent.payload[0] = static_cast<uint32_t>(CameraParam::AUTO_FOCUS);
+                        aTargetEvent.payload[1] = 0;
+                        if (!frameHandler0->waitForEvent(aTargetEvent, aNotification)) {
+                            LOG(WARNING) << "A timer is expired before a target event is fired.";
+                        }
+                    });
+
+            // Wait until a lister starts.
+            std::unique_lock<std::mutex> lock(eventLock);
+            auto timer = std::chrono::system_clock::now();
+            while (!listening) {
+                eventCond.wait_until(lock, timer + 1s);
+            }
+            lock.unlock();
+
+            // Try to turn off auto-focus
+            ASSERT_TRUE(pCam1->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
+            for (auto&& v : values) {
+                EXPECT_EQ(v, 0);
+            }
+
+            // Join a listener
+            if (listener.joinable()) {
+                listener.join();
+            }
+
+            // Make sure AUTO_FOCUS is off.
+            ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType),
+                      EvsEventType::PARAMETER_CHANGED);
+        }
+
+        // Try to program a parameter with a random value [minVal, maxVal] after
+        // rounding it down.
+        int32_t val0 = range.min + (std::rand() % (range.max - range.min));
+        val0 = val0 - (val0 % range.step);
+
+        std::thread listener = std::thread(
+                [&frameHandler1, &aNotification, &listening, &eventCond, &cam1Cmds, val0] {
+                    listening = true;
+                    eventCond.notify_all();
+
+                    EvsEventDesc aTargetEvent;
+                    aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+                    aTargetEvent.payload[0] = static_cast<uint32_t>(cam1Cmds[0]);
+                    aTargetEvent.payload[1] = val0;
+                    if (!frameHandler1->waitForEvent(aTargetEvent, aNotification)) {
+                        LOG(WARNING) << "A timer is expired before a target event is fired.";
+                    }
+                });
+
+        // Wait until a lister starts.
+        listening = false;
+        std::unique_lock<std::mutex> lock(eventLock);
+        auto timer = std::chrono::system_clock::now();
+        while (!listening) {
+            eventCond.wait_until(lock, timer + 1s);
+        }
+        lock.unlock();
+
+        values.clear();
+        ASSERT_TRUE(pCam1->setIntParameter(cam1Cmds[0], val0, &values).isOk());
+        for (auto&& v : values) {
+            EXPECT_EQ(val0, v);
+        }
+
+        // Join a listener
+        if (listener.joinable()) {
+            listener.join();
+        }
+
+        // Verify a change notification
+        ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType), EvsEventType::PARAMETER_CHANGED);
+        ASSERT_EQ(static_cast<CameraParam>(aNotification.payload[0]), cam1Cmds[0]);
+        for (auto&& v : values) {
+            ASSERT_EQ(v, static_cast<int32_t>(aNotification.payload[1]));
+        }
+
+        listener = std::thread([&frameHandler1, &aNotification, &listening, &eventCond] {
+            listening = true;
+            eventCond.notify_all();
+
+            EvsEventDesc aTargetEvent;
+            aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
+            if (!frameHandler1->waitForEvent(aTargetEvent, aNotification, true)) {
+                LOG(WARNING) << "A timer is expired before a target event is fired.";
+            }
+        });
+
+        // Wait until a lister starts.
+        listening = false;
+        lock.lock();
+        timer = std::chrono::system_clock::now();
+        while (!listening) {
+            eventCond.wait_until(lock, timer + 1s);
+        }
+        lock.unlock();
+
+        // Client 0 steals a primary client role
+        ASSERT_TRUE(pCam0->forcePrimaryClient(pDisplay).isOk());
+
+        // Join a listener
+        if (listener.joinable()) {
+            listener.join();
+        }
+
+        ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType), EvsEventType::MASTER_RELEASED);
+
+        // Client 0 programs a parameter
+        val0 = range.min + (std::rand() % (range.max - range.min));
+
+        // Rounding down
+        val0 = val0 - (val0 % range.step);
+
+        if (cam0Cmds[0] == CameraParam::ABSOLUTE_FOCUS) {
+            std::thread listener =
+                    std::thread([&frameHandler1, &aNotification, &listening, &eventCond] {
+                        listening = true;
+                        eventCond.notify_all();
+
+                        EvsEventDesc aTargetEvent;
+                        aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+                        aTargetEvent.payload[0] = static_cast<uint32_t>(CameraParam::AUTO_FOCUS);
+                        aTargetEvent.payload[1] = 0;
+                        if (!frameHandler1->waitForEvent(aTargetEvent, aNotification)) {
+                            LOG(WARNING) << "A timer is expired before a target event is fired.";
+                        }
+                    });
+
+            // Wait until a lister starts.
+            std::unique_lock<std::mutex> lock(eventLock);
+            auto timer = std::chrono::system_clock::now();
+            while (!listening) {
+                eventCond.wait_until(lock, timer + 1s);
+            }
+            lock.unlock();
+
+            // Try to turn off auto-focus
+            values.clear();
+            ASSERT_TRUE(pCam0->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
+            for (auto&& v : values) {
+                EXPECT_EQ(v, 0);
+            }
+
+            // Join a listener
+            if (listener.joinable()) {
+                listener.join();
+            }
+
+            // Make sure AUTO_FOCUS is off.
+            ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType),
+                      EvsEventType::PARAMETER_CHANGED);
+        }
+
+        listener = std::thread(
+                [&frameHandler0, &aNotification, &listening, &eventCond, &cam0Cmds, val0] {
+                    listening = true;
+                    eventCond.notify_all();
+
+                    EvsEventDesc aTargetEvent;
+                    aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
+                    aTargetEvent.payload[0] = static_cast<uint32_t>(cam0Cmds[0]);
+                    aTargetEvent.payload[1] = val0;
+                    if (!frameHandler0->waitForEvent(aTargetEvent, aNotification)) {
+                        LOG(WARNING) << "A timer is expired before a target event is fired.";
+                    }
+                });
+
+        // Wait until a lister starts.
+        listening = false;
+        timer = std::chrono::system_clock::now();
+        lock.lock();
+        while (!listening) {
+            eventCond.wait_until(lock, timer + 1s);
+        }
+        lock.unlock();
+
+        values.clear();
+        ASSERT_TRUE(pCam0->setIntParameter(cam0Cmds[0], val0, &values).isOk());
+
+        // Join a listener
+        if (listener.joinable()) {
+            listener.join();
+        }
+        // Verify a change notification
+        ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType), EvsEventType::PARAMETER_CHANGED);
+        ASSERT_EQ(static_cast<CameraParam>(aNotification.payload[0]), cam0Cmds[0]);
+        for (auto&& v : values) {
+            ASSERT_EQ(v, static_cast<int32_t>(aNotification.payload[1]));
+        }
+
+        // Turn off the display (yes, before the stream stops -- it should be handled)
+        ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::NOT_VISIBLE).isOk());
+
+        // Shut down the streamer
+        frameHandler0->shutdown();
+        frameHandler1->shutdown();
+
+        // Explicitly release the camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam0).isOk());
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam1).isOk());
+        mActiveCameras.clear();
+    }
+
+    // Explicitly release the display
+    ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+}
+
+/*
+ * CameraUseStreamConfigToDisplay:
+ * End to end test of data flowing from the camera to the display.  Similar to
+ * CameraToDisplayRoundTrip test case but this case retrieves available stream
+ * configurations from EVS and uses one of them to start a video stream.
+ */
+TEST_P(EvsAidlTest, CameraUseStreamConfigToDisplay) {
+    LOG(INFO) << "Starting CameraUseStreamConfigToDisplay test";
+
+    // Get the camera list
+    loadCameraList();
+
+    // Request available display IDs
+    uint8_t targetDisplayId = 0;
+    std::vector<uint8_t> displayIds;
+    ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
+    EXPECT_GT(displayIds.size(), 0);
+    targetDisplayId = displayIds[0];
+
+    // Request exclusive access to the EVS display
+    std::shared_ptr<IEvsDisplay> pDisplay;
+    ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
+    EXPECT_NE(pDisplay, nullptr);
+
+    // Test each reported camera
+    for (auto&& cam : mCameraInfo) {
+        // choose a configuration that has a frame rate faster than minReqFps.
+        Stream targetCfg = {};
+        const int32_t minReqFps = 15;
+        int32_t maxArea = 0;
+        camera_metadata_entry_t streamCfgs;
+        bool foundCfg = false;
+        if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
+                                        ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+                                        &streamCfgs)) {
+            // Stream configurations are found in metadata
+            RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+                    if (ptr->width * ptr->height > maxArea && ptr->framerate >= minReqFps) {
+                        targetCfg.width = ptr->width;
+                        targetCfg.height = ptr->height;
+
+                        maxArea = ptr->width * ptr->height;
+                        foundCfg = true;
+                    }
+                }
+                ++ptr;
+            }
+        }
+        targetCfg.format = static_cast<PixelFormat>(HAL_PIXEL_FORMAT_RGBA_8888);
+
+        if (!foundCfg) {
+            // Current EVS camera does not provide stream configurations in the
+            // metadata.
+            continue;
+        }
+
+        std::shared_ptr<IEvsCamera> pCam;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+        EXPECT_NE(pCam, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam);
+
+        // Set up a frame receiver object which will fire up its own thread.
+        std::shared_ptr<FrameHandler> frameHandler =
+                std::make_shared<FrameHandler>(pCam, cam, pDisplay, FrameHandler::eAutoReturn);
+        EXPECT_NE(frameHandler, nullptr);
+
+        // Activate the display
+        ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME).isOk());
+
+        // Start the camera's video stream
+        ASSERT_TRUE(frameHandler->startStream());
+
+        // Wait a while to let the data flow
+        static const int kSecondsToWait = 5;
+        const int streamTimeMs =
+                kSecondsToWait * kSecondsToMilliseconds - kMaxStreamStartMilliseconds;
+        const unsigned minimumFramesExpected =
+                streamTimeMs * kMinimumFramesPerSecond / kSecondsToMilliseconds;
+        sleep(kSecondsToWait);
+        unsigned framesReceived = 0;
+        unsigned framesDisplayed = 0;
+        frameHandler->getFramesCounters(&framesReceived, &framesDisplayed);
+        EXPECT_EQ(framesReceived, framesDisplayed);
+        EXPECT_GE(framesDisplayed, minimumFramesExpected);
+
+        // Turn off the display (yes, before the stream stops -- it should be handled)
+        ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::NOT_VISIBLE).isOk());
+
+        // Shut down the streamer
+        frameHandler->shutdown();
+
+        // Explicitly release the camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+        mActiveCameras.clear();
+    }
+
+    // Explicitly release the display
+    ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
+}
+
+/*
+ * MultiCameraStreamUseConfig:
+ * Verify that each client can start and stop video streams on the same
+ * underlying camera with same configuration.
+ */
+TEST_P(EvsAidlTest, MultiCameraStreamUseConfig) {
+    LOG(INFO) << "Starting MultiCameraStream test";
+
+    if (mIsHwModule) {
+        // This test is not for HW module implementation.
+        return;
+    }
+
+    // Get the camera list
+    loadCameraList();
+
+    // Test each reported camera
+    for (auto&& cam : mCameraInfo) {
+        // choose a configuration that has a frame rate faster than minReqFps.
+        Stream targetCfg = {};
+        const int32_t minReqFps = 15;
+        int32_t maxArea = 0;
+        camera_metadata_entry_t streamCfgs;
+        bool foundCfg = false;
+        if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
+                                        ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+                                        &streamCfgs)) {
+            // Stream configurations are found in metadata
+            RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+                    if (ptr->width * ptr->height > maxArea && ptr->framerate >= minReqFps) {
+                        targetCfg.width = ptr->width;
+                        targetCfg.height = ptr->height;
+
+                        maxArea = ptr->width * ptr->height;
+                        foundCfg = true;
+                    }
+                }
+                ++ptr;
+            }
+        }
+        targetCfg.format = static_cast<PixelFormat>(HAL_PIXEL_FORMAT_RGBA_8888);
+
+        if (!foundCfg) {
+            LOG(INFO) << "Device " << cam.id
+                      << " does not provide a list of supported stream configurations, skipped";
+            continue;
+        }
+
+        // Create the first camera client with a selected stream configuration.
+        std::shared_ptr<IEvsCamera> pCam0;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam0).isOk());
+        EXPECT_NE(pCam0, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam0);
+
+        // Try to create the second camera client with different stream
+        // configuration.
+        int32_t id = targetCfg.id;
+        targetCfg.id += 1;  // EVS manager sees only the stream id.
+        std::shared_ptr<IEvsCamera> pCam1;
+        ASSERT_FALSE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
+
+        // Try again with same stream configuration.
+        targetCfg.id = id;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
+        EXPECT_NE(pCam1, nullptr);
+
+        // Set up per-client frame receiver objects which will fire up its own thread
+        std::shared_ptr<FrameHandler> frameHandler0 =
+                std::make_shared<FrameHandler>(pCam0, cam, nullptr, FrameHandler::eAutoReturn);
+        std::shared_ptr<FrameHandler> frameHandler1 =
+                std::make_shared<FrameHandler>(pCam1, cam, nullptr, FrameHandler::eAutoReturn);
+        EXPECT_NE(frameHandler0, nullptr);
+        EXPECT_NE(frameHandler1, nullptr);
+
+        // Start the camera's video stream via client 0
+        ASSERT_TRUE(frameHandler0->startStream());
+        ASSERT_TRUE(frameHandler1->startStream());
+
+        // Ensure the stream starts
+        frameHandler0->waitForFrameCount(1);
+        frameHandler1->waitForFrameCount(1);
+
+        nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC);
+
+        // Wait a bit, then ensure both clients get at least the required minimum number of frames
+        sleep(5);
+        nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
+        unsigned framesReceived0 = 0, framesReceived1 = 0;
+        frameHandler0->getFramesCounters(&framesReceived0, nullptr);
+        frameHandler1->getFramesCounters(&framesReceived1, nullptr);
+        framesReceived0 = framesReceived0 - 1;  // Back out the first frame we already waited for
+        framesReceived1 = framesReceived1 - 1;  // Back out the first frame we already waited for
+        nsecs_t runTime = end - firstFrame;
+        float framesPerSecond0 = framesReceived0 / (runTime * kNanoToSeconds);
+        float framesPerSecond1 = framesReceived1 / (runTime * kNanoToSeconds);
+        LOG(INFO) << "Measured camera rate " << std::scientific << framesPerSecond0 << " fps and "
+                  << framesPerSecond1 << " fps";
+        EXPECT_GE(framesPerSecond0, kMinimumFramesPerSecond);
+        EXPECT_GE(framesPerSecond1, kMinimumFramesPerSecond);
+
+        // Shutdown one client
+        frameHandler0->shutdown();
+
+        // Read frame counters again
+        frameHandler0->getFramesCounters(&framesReceived0, nullptr);
+        frameHandler1->getFramesCounters(&framesReceived1, nullptr);
+
+        // Wait a bit again
+        sleep(5);
+        unsigned framesReceivedAfterStop0 = 0, framesReceivedAfterStop1 = 0;
+        frameHandler0->getFramesCounters(&framesReceivedAfterStop0, nullptr);
+        frameHandler1->getFramesCounters(&framesReceivedAfterStop1, nullptr);
+        EXPECT_EQ(framesReceived0, framesReceivedAfterStop0);
+        EXPECT_LT(framesReceived1, framesReceivedAfterStop1);
+
+        // Shutdown another
+        frameHandler1->shutdown();
+
+        // Explicitly release the camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam0).isOk());
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam1).isOk());
+        mActiveCameras.clear();
+    }
+}
+
+/*
+ * LogicalCameraMetadata:
+ * Opens logical camera reported by the enumerator and validate its metadata by
+ * checking its capability and locating supporting physical camera device
+ * identifiers.
+ */
+TEST_P(EvsAidlTest, LogicalCameraMetadata) {
+    LOG(INFO) << "Starting LogicalCameraMetadata test";
+
+    // Get the camera list
+    loadCameraList();
+
+    // Open and close each camera twice
+    for (auto&& cam : mCameraInfo) {
+        bool isLogicalCam = false;
+        auto devices = getPhysicalCameraIds(cam.id, isLogicalCam);
+        if (isLogicalCam) {
+            ASSERT_GE(devices.size(), 1) << "Logical camera device must have at least one physical "
+                                            "camera device ID in its metadata.";
+        }
+    }
+}
+
+/*
+ * CameraStreamExternalBuffering:
+ * This is same with CameraStreamBuffering except frame buffers are allocated by
+ * the test client and then imported by EVS framework.
+ */
+TEST_P(EvsAidlTest, CameraStreamExternalBuffering) {
+    LOG(INFO) << "Starting CameraStreamExternalBuffering test";
+
+    // Arbitrary constant (should be > 1 and not too big)
+    static const unsigned int kBuffersToHold = 3;
+
+    // Get the camera list
+    loadCameraList();
+
+    // Acquire the graphics buffer allocator
+    android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get());
+    const auto usage =
+            GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
+
+    // Test each reported camera
+    for (auto&& cam : mCameraInfo) {
+        // Read a target resolution from the metadata
+        Stream targetCfg = getFirstStreamConfiguration(
+                reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        // Allocate buffers to use
+        std::vector<BufferDesc> buffers;
+        buffers.resize(kBuffersToHold);
+        for (auto i = 0; i < kBuffersToHold; ++i) {
+            unsigned pixelsPerLine;
+            buffer_handle_t memHandle = nullptr;
+            android::status_t result =
+                    alloc.allocate(targetCfg.width, targetCfg.height,
+                                   static_cast<android::PixelFormat>(targetCfg.format),
+                                   /* layerCount = */ 1, usage, &memHandle, &pixelsPerLine,
+                                   /* graphicBufferId = */ 0,
+                                   /* requestorName = */ "CameraStreamExternalBufferingTest");
+            if (result != android::NO_ERROR) {
+                LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
+                // Release previous allocated buffers
+                for (auto j = 0; j < i; j++) {
+                    alloc.free(::android::dupFromAidl(buffers[i].buffer.handle));
+                }
+                return;
+            } else {
+                BufferDesc buf;
+                HardwareBufferDescription* pDesc =
+                        reinterpret_cast<HardwareBufferDescription*>(&buf.buffer.description);
+                pDesc->width = targetCfg.width;
+                pDesc->height = targetCfg.height;
+                pDesc->layers = 1;
+                pDesc->format = targetCfg.format;
+                pDesc->usage = static_cast<BufferUsage>(usage);
+                pDesc->stride = pixelsPerLine;
+                buf.buffer.handle = ::android::dupToAidl(memHandle);
+                buf.bufferId = i;  // Unique number to identify this buffer
+                buffers[i] = std::move(buf);
+            }
+        }
+
+        bool isLogicalCam = false;
+        getPhysicalCameraIds(cam.id, isLogicalCam);
+
+        std::shared_ptr<IEvsCamera> pCam;
+        ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
+        EXPECT_NE(pCam, nullptr);
+
+        // Store a camera handle for a clean-up
+        mActiveCameras.push_back(pCam);
+
+        // Request to import buffers
+        int delta = 0;
+        auto status = pCam->importExternalBuffers(buffers, &delta);
+        if (isLogicalCam) {
+            ASSERT_FALSE(status.isOk());
+            continue;
+        }
+
+        ASSERT_TRUE(status.isOk());
+        EXPECT_GE(delta, kBuffersToHold);
+
+        // Set up a frame receiver object which will fire up its own thread.
+        std::shared_ptr<FrameHandler> frameHandler =
+                std::make_shared<FrameHandler>(pCam, cam, nullptr, FrameHandler::eNoAutoReturn);
+        EXPECT_NE(frameHandler, nullptr);
+
+        // Start the camera's video stream
+        ASSERT_TRUE(frameHandler->startStream());
+
+        // Check that the video stream stalls once we've gotten exactly the number of buffers
+        // we requested since we told the frameHandler not to return them.
+        sleep(1);  // 1 second should be enough for at least 5 frames to be delivered worst case
+        unsigned framesReceived = 0;
+        frameHandler->getFramesCounters(&framesReceived, nullptr);
+        ASSERT_LE(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
+
+        // Give back one buffer
+        EXPECT_TRUE(frameHandler->returnHeldBuffer());
+
+        // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
+        // filled since we require 10fps minimum -- but give a 10% allowance just in case.
+        unsigned framesReceivedAfter = 0;
+        usleep(110 * kMillisecondsToMicroseconds);
+        frameHandler->getFramesCounters(&framesReceivedAfter, nullptr);
+        EXPECT_EQ(framesReceived + 1, framesReceivedAfter) << "Stream should've resumed";
+
+        // Even when the camera pointer goes out of scope, the FrameHandler object will
+        // keep the stream alive unless we tell it to shutdown.
+        // Also note that the FrameHandle and the Camera have a mutual circular reference, so
+        // we have to break that cycle in order for either of them to get cleaned up.
+        frameHandler->shutdown();
+
+        // Explicitly release the camera
+        ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
+        mActiveCameras.clear();
+        // Release buffers
+        for (auto& b : buffers) {
+            alloc.free(::android::dupFromAidl(b.buffer.handle));
+        }
+        buffers.resize(0);
+    }
+}
+
+/*
+ * UltrasonicsArrayOpenClean:
+ * Opens each ultrasonics arrays reported by the enumerator and then explicitly closes it via a
+ * call to closeUltrasonicsArray. Then repeats the test to ensure all ultrasonics arrays
+ * can be reopened.
+ */
+TEST_P(EvsAidlTest, UltrasonicsArrayOpenClean) {
+    LOG(INFO) << "Starting UltrasonicsArrayOpenClean test";
+
+    // Get the ultrasonics array list
+    loadUltrasonicsArrayList();
+
+    // Open and close each ultrasonics array twice
+    for (auto&& ultraInfo : mUltrasonicsArraysInfo) {
+        for (int pass = 0; pass < 2; pass++) {
+            std::shared_ptr<IEvsUltrasonicsArray> pUltrasonicsArray;
+            ASSERT_TRUE(
+                    mEnumerator
+                            ->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId, &pUltrasonicsArray)
+                            .isOk());
+            EXPECT_NE(pUltrasonicsArray, nullptr);
+
+            // Verify that this ultrasonics array self-identifies correctly
+            UltrasonicsArrayDesc desc;
+            ASSERT_TRUE(pUltrasonicsArray->getUltrasonicArrayInfo(&desc).isOk());
+            EXPECT_EQ(ultraInfo.ultrasonicsArrayId, desc.ultrasonicsArrayId);
+            LOG(DEBUG) << "Found ultrasonics array " << ultraInfo.ultrasonicsArrayId;
+
+            // Explicitly close the ultrasonics array so resources are released right away
+            ASSERT_TRUE(mEnumerator->closeUltrasonicsArray(pUltrasonicsArray).isOk());
+        }
+    }
+}
+
+// Starts a stream and verifies all data received is valid.
+TEST_P(EvsAidlTest, UltrasonicsVerifyStreamData) {
+    LOG(INFO) << "Starting UltrasonicsVerifyStreamData";
+
+    // Get the ultrasonics array list
+    loadUltrasonicsArrayList();
+
+    // For each ultrasonics array.
+    for (auto&& ultraInfo : mUltrasonicsArraysInfo) {
+        LOG(DEBUG) << "Testing ultrasonics array: " << ultraInfo.ultrasonicsArrayId;
+
+        std::shared_ptr<IEvsUltrasonicsArray> pUltrasonicsArray;
+        ASSERT_TRUE(
+                mEnumerator->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId, &pUltrasonicsArray)
+                        .isOk());
+        EXPECT_NE(pUltrasonicsArray, nullptr);
+
+        std::shared_ptr<FrameHandlerUltrasonics> frameHandler =
+                std::make_shared<FrameHandlerUltrasonics>(pUltrasonicsArray);
+        EXPECT_NE(frameHandler, nullptr);
+
+        // Start stream.
+        ASSERT_TRUE(pUltrasonicsArray->startStream(frameHandler).isOk());
+
+        // Wait 5 seconds to receive frames.
+        sleep(5);
+
+        // Stop stream.
+        ASSERT_TRUE(pUltrasonicsArray->stopStream().isOk());
+
+        EXPECT_GT(frameHandler->getReceiveFramesCount(), 0);
+        EXPECT_TRUE(frameHandler->areAllFramesValid());
+
+        // Explicitly close the ultrasonics array so resources are released right away
+        ASSERT_TRUE(mEnumerator->closeUltrasonicsArray(pUltrasonicsArray).isOk());
+    }
+}
+
+// Sets frames in flight before and after start of stream and verfies success.
+TEST_P(EvsAidlTest, UltrasonicsSetFramesInFlight) {
+    LOG(INFO) << "Starting UltrasonicsSetFramesInFlight";
+
+    // Get the ultrasonics array list
+    loadUltrasonicsArrayList();
+
+    // For each ultrasonics array.
+    for (auto&& ultraInfo : mUltrasonicsArraysInfo) {
+        LOG(DEBUG) << "Testing ultrasonics array: " << ultraInfo.ultrasonicsArrayId;
+
+        std::shared_ptr<IEvsUltrasonicsArray> pUltrasonicsArray;
+        ASSERT_TRUE(
+                mEnumerator->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId, &pUltrasonicsArray)
+                        .isOk());
+        EXPECT_NE(pUltrasonicsArray, nullptr);
+
+        ASSERT_TRUE(pUltrasonicsArray->setMaxFramesInFlight(10).isOk());
+
+        std::shared_ptr<FrameHandlerUltrasonics> frameHandler =
+                std::make_shared<FrameHandlerUltrasonics>(pUltrasonicsArray);
+        EXPECT_NE(frameHandler, nullptr);
+
+        // Start stream.
+        ASSERT_TRUE(pUltrasonicsArray->startStream(frameHandler).isOk());
+        ASSERT_TRUE(pUltrasonicsArray->setMaxFramesInFlight(5).isOk());
+
+        // Stop stream.
+        ASSERT_TRUE(pUltrasonicsArray->stopStream().isOk());
+
+        // Explicitly close the ultrasonics array so resources are released right away
+        ASSERT_TRUE(mEnumerator->closeUltrasonicsArray(pUltrasonicsArray).isOk());
+    }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EvsAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, EvsAidlTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IEvsEnumerator::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/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/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index f8df6e6..970d044 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -154,7 +154,7 @@
         return toInt(result.error());
     }
 
-    void onSetValues(const std::vector<SetValueResult> results) {
+    void onSetValues(std::vector<SetValueResult> results) {
         for (auto& result : results) {
             mSetValueResults.push_back(result);
         }
@@ -162,7 +162,7 @@
 
     const std::vector<SetValueResult>& getSetValueResults() { return mSetValueResults; }
 
-    void onGetValues(const std::vector<GetValueResult> results) {
+    void onGetValues(std::vector<GetValueResult> results) {
         for (auto& result : results) {
             mGetValueResults.push_back(result);
         }
@@ -170,7 +170,7 @@
 
     const std::vector<GetValueResult>& getGetValueResults() { return mGetValueResults; }
 
-    void onPropertyChangeEvent(const std::vector<VehiclePropValue>& values) {
+    void onPropertyChangeEvent(std::vector<VehiclePropValue> values) {
         for (auto& value : values) {
             mChangedProperties.push_back(value);
         }
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
index 013d177..a7fcdcf 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
@@ -37,6 +37,7 @@
 #include <aidl/android/hardware/automotive/vehicle/SetValueResult.h>
 #include <aidl/android/hardware/automotive/vehicle/SetValueResults.h>
 #include <aidl/android/hardware/automotive/vehicle/StatusCode.h>
+#include <aidl/android/hardware/automotive/vehicle/SubscribeOptions.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleArea.h>
diff --git a/automotive/vehicle/aidl/impl/vhal/Android.bp b/automotive/vehicle/aidl/impl/vhal/Android.bp
index 454fea5..0132e6f 100644
--- a/automotive/vehicle/aidl/impl/vhal/Android.bp
+++ b/automotive/vehicle/aidl/impl/vhal/Android.bp
@@ -56,6 +56,9 @@
     srcs: [
         "src/ConnectedClient.cpp",
         "src/DefaultVehicleHal.cpp",
+        "src/PendingRequestPool.cpp",
+        "src/RecurrentTimer.cpp",
+        "src/SubscriptionManager.cpp",
     ],
     static_libs: [
         "VehicleHalUtils",
diff --git a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
index 43a9603..d8516b1 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
@@ -17,6 +17,8 @@
 #ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_
 #define android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_
 
+#include "PendingRequestPool.h"
+
 #include <VehicleHalTypes.h>
 
 #include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
@@ -40,12 +42,31 @@
 class ConnectedClient {
   public:
     ConnectedClient(
+            std::shared_ptr<PendingRequestPool> requestPool,
             std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>
                     callback);
 
     virtual ~ConnectedClient() = default;
 
+    // Gets the unique ID for this client.
+    const void* id();
+
+    // Add client requests. The requests would be registered as pending requests until
+    // {@code tryFinishRequests} is called for them.
+    // Returns {@code INVALID_ARG} error if any of the requestIds are duplicate with one of the
+    // pending request IDs or {@code TRY_AGAIN} error if the pending request pool is full and could
+    // no longer add requests.
+    ::android::base::Result<void> addRequests(const std::unordered_set<int64_t>& requestIds);
+
+    // Mark the requests as finished. Returns a list of request IDs that was pending and has been
+    // finished. It must be a set of the requested request IDs.
+    std::unordered_set<int64_t> tryFinishRequests(const std::unordered_set<int64_t>& requestIds);
+
   protected:
+    // Gets the callback to be called when the request for this client has timeout.
+    virtual std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> getTimeoutCallback() = 0;
+
+    const std::shared_ptr<PendingRequestPool> mRequestPool;
     const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>
             mCallback;
 };
@@ -56,6 +77,7 @@
 class GetSetValuesClient final : public ConnectedClient {
   public:
     GetSetValuesClient(
+            std::shared_ptr<PendingRequestPool> requestPool,
             std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>
                     callback);
 
@@ -69,11 +91,48 @@
     // Gets the callback to be called when the request for this client has finished.
     std::shared_ptr<const std::function<void(std::vector<ResultType>)>> getResultCallback();
 
+  protected:
+    // Gets the callback to be called when the request for this client has timeout.
+    std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> getTimeoutCallback() override;
+
   private:
     // The following members are only initialized during construction.
+    std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> mTimeoutCallback;
     std::shared_ptr<const std::function<void(std::vector<ResultType>)>> mResultCallback;
 };
 
+// A class to represent a client that calls {@code IVehicle.subscribe}.
+class SubscriptionClient final : public ConnectedClient {
+  public:
+    SubscriptionClient(
+            std::shared_ptr<PendingRequestPool> requestPool,
+            std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>
+                    callback);
+
+    // Gets the callback to be called when the request for this client has finished.
+    std::shared_ptr<const std::function<
+            void(std::vector<::aidl::android::hardware::automotive::vehicle::GetValueResult>)>>
+    getResultCallback();
+
+  protected:
+    // Gets the callback to be called when the request for this client has timeout.
+    std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> getTimeoutCallback() override;
+
+  private:
+    // The following members are only initialized during construction.
+    std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> mTimeoutCallback;
+    std::shared_ptr<const std::function<void(
+            std::vector<::aidl::android::hardware::automotive::vehicle::GetValueResult>)>>
+            mResultCallback;
+
+    static void onGetValueResults(
+            const void* clientId,
+            std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>
+                    callback,
+            std::shared_ptr<PendingRequestPool> requestPool,
+            std::vector<::aidl::android::hardware::automotive::vehicle::GetValueResult> results);
+};
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index 4ee3ee9..b0423a3 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -19,6 +19,8 @@
 
 #include "ConnectedClient.h"
 #include "ParcelableUtils.h"
+#include "PendingRequestPool.h"
+#include "SubscriptionManager.h"
 
 #include <IVehicleHardware.h>
 #include <VehicleUtils.h>
@@ -28,6 +30,7 @@
 #include <android/binder_auto_utils.h>
 
 #include <memory>
+#include <mutex>
 #include <unordered_map>
 #include <vector>
 
@@ -50,6 +53,8 @@
 
     explicit DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware);
 
+    ~DefaultVehicleHal();
+
     ::ndk::ScopedAStatus getAllPropConfigs(
             ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
             override;
@@ -88,19 +93,32 @@
             GetSetValuesClient<::aidl::android::hardware::automotive::vehicle::SetValueResult,
                                ::aidl::android::hardware::automotive::vehicle::SetValueResults>;
 
+    // The default timeout of get or set value requests is 30s.
+    // TODO(b/214605968): define TIMEOUT_IN_NANO in IVehicle and allow getValues/setValues/subscribe
+    // to specify custom timeouts.
+    static constexpr int64_t TIMEOUT_IN_NANO = 30'000'000'000;
     const std::unique_ptr<IVehicleHardware> mVehicleHardware;
 
     // mConfigsByPropId and mConfigFile are only modified during initialization, so no need to
     // lock guard them.
     std::unordered_map<int32_t, ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
             mConfigsByPropId;
+    // Only modified in constructor, so thread-safe.
     std::unique_ptr<::ndk::ScopedFileDescriptor> mConfigFile;
+    // PendingRequestPool is thread-safe.
+    std::shared_ptr<PendingRequestPool> mPendingRequestPool;
+    // SubscriptionManager is thread-safe.
+    std::unique_ptr<SubscriptionManager> mSubscriptionManager;
 
     std::mutex mLock;
     std::unordered_map<CallbackType, std::shared_ptr<GetValuesClient>> mGetValuesClients
             GUARDED_BY(mLock);
     std::unordered_map<CallbackType, std::shared_ptr<SetValuesClient>> mSetValuesClients
             GUARDED_BY(mLock);
+    std::unordered_map<CallbackType, std::shared_ptr<SubscriptionClient>> mSubscriptionClients
+            GUARDED_BY(mLock);
+    // An increasing request ID we keep for subscribe clients.
+    std::unordered_map<CallbackType, int64_t> mSubscribeIdByClient GUARDED_BY(mLock);
 
     template <class T>
     std::shared_ptr<T> getOrCreateClient(
@@ -109,6 +127,22 @@
 
     ::android::base::Result<void> checkProperty(
             const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+
+    ::android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
+            const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest>&
+                    requests);
+
+    ::android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
+            const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest>&
+                    requests);
+
+    void getValueFromHardwareCallCallback(
+            const CallbackType& callback,
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+
+    // Test-only
+    // Set the default timeout for pending requests.
+    void setTimeout(int64_t timeoutInNano);
 };
 
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h b/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h
index dcb15b9..4b7c2f3 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h
@@ -31,19 +31,18 @@
 
 template <class T1, class T2>
 ::ndk::ScopedAStatus vectorToStableLargeParcelable(std::vector<T1>&& values, T2* output) {
+    output->payloads = std::move(values);
     auto result = ::android::automotive::car_binder_lib::LargeParcelableBase::
-            parcelableVectorToStableLargeParcelable(values);
+            parcelableToStableLargeParcelable(*output);
     if (!result.ok()) {
         return toScopedAStatus(
                 result, ::aidl::android::hardware::automotive::vehicle::StatusCode::INTERNAL_ERROR);
     }
     auto& fd = result.value();
-    if (fd == nullptr) {
-        // If we no longer needs values, move it inside the payloads to avoid copying.
-        output->payloads = std::move(values);
-    } else {
+    if (fd != nullptr) {
         // Move the returned ScopedFileDescriptor pointer to ScopedFileDescriptor value in
         // 'sharedMemoryFd' field.
+        output->payloads.clear();
         output->sharedMemoryFd = std::move(*fd);
     }
     return ::ndk::ScopedAStatus::ok();
@@ -57,12 +56,13 @@
     return vectorToStableLargeParcelable(std::move(valuesCopy), output);
 }
 
-template <class T1, class T2>
-::android::base::expected<std::vector<T1>, ::ndk::ScopedAStatus> stableLargeParcelableToVector(
-        const T2& largeParcelable) {
-    ::android::base::Result<std::optional<std::vector<T1>>> result =
-            ::android::automotive::car_binder_lib::LargeParcelableBase::
-                    stableLargeParcelableToParcelableVector<T1>(largeParcelable.sharedMemoryFd);
+template <class T>
+::android::base::expected<
+        ::android::automotive::car_binder_lib::LargeParcelableBase::BorrowedOwnedObject<T>,
+        ::ndk::ScopedAStatus>
+fromStableLargeParcelable(const T& largeParcelable) {
+    auto result = ::android::automotive::car_binder_lib::LargeParcelableBase::
+            stableLargeParcelableToParcelable(largeParcelable);
 
     if (!result.ok()) {
         return ::android::base::unexpected(toScopedAStatus(
@@ -70,15 +70,7 @@
                 "failed to parse large parcelable"));
     }
 
-    if (!result.value().has_value()) {
-        return ::android::base::unexpected(
-                ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
-                        toInt(::aidl::android::hardware::automotive::vehicle::StatusCode::
-                                      INVALID_ARG),
-                        "empty request"));
-    }
-
-    return std::move(result.value().value());
+    return std::move(result.value());
 }
 
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/include/PendingRequestPool.h b/automotive/vehicle/aidl/impl/vhal/include/PendingRequestPool.h
new file mode 100644
index 0000000..efb3315
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/include/PendingRequestPool.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_automotive_vehicle_aidl_impl_vhal_include_PendingRequestPool_H_
+#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_PendingRequestPool_H_
+
+#include <android-base/result.h>
+#include <android-base/thread_annotations.h>
+
+#include <atomic>
+#include <list>
+#include <mutex>
+#include <thread>
+#include <unordered_map>
+#include <unordered_set>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// A thread-safe pending request pool that tracks whether each request has timed-out.
+class PendingRequestPool final {
+  public:
+    using TimeoutCallbackFunc = std::function<void(const std::unordered_set<int64_t>&)>;
+
+    explicit PendingRequestPool(int64_t timeoutInSec);
+
+    ~PendingRequestPool();
+
+    // Adds a list of requests to the request pool.
+    // The clientId is the key for all the requests. It could be a number or an address to a data
+    // structure that represents a client. The caller must maintain this data structure.
+    // All the request IDs must be unique for one client, if any of the requestIds is duplicate with
+    // any pending request IDs for the client, this function returns error and no requests would be
+    // added. Otherwise, they would be added to the request pool.
+    // The callback would be called if requests are not finished within {@code mTimeoutInNano}
+    // seconds.
+    android::base::Result<void> addRequests(const void* clientId,
+                                            const std::unordered_set<int64_t>& requestIds,
+                                            std::shared_ptr<const TimeoutCallbackFunc> callback);
+
+    // Checks whether the request is currently pending.
+    bool isRequestPending(const void* clientId, int64_t requestId) const;
+
+    // Tries to mark the requests as finished and remove them from the pool if the request is
+    // currently pending. Returns the list of request that is pending and has been finished
+    // successfully. This function would try to finish any valid requestIds even though some of the
+    // requestIds are not valid.
+    std::unordered_set<int64_t> tryFinishRequests(const void* clientId,
+                                                  const std::unordered_set<int64_t>& requestIds);
+
+    // Returns how many pending requests in the pool, for testing purpose.
+    size_t countPendingRequests(const void* clientId) const;
+
+    size_t countPendingRequests() const;
+
+  private:
+    // The maximum number of pending requests allowed per client. If exceeds this number, adding
+    // more requests would fail. This is to prevent spamming from client.
+    static constexpr size_t MAX_PENDING_REQUEST_PER_CLIENT = 10000;
+
+    struct PendingRequest {
+        std::unordered_set<int64_t> requestIds;
+        int64_t timeoutTimestamp;
+        std::shared_ptr<const TimeoutCallbackFunc> callback;
+    };
+
+    int64_t mTimeoutInNano;
+    mutable std::mutex mLock;
+    std::unordered_map<const void*, std::list<PendingRequest>> mPendingRequestsByClient
+            GUARDED_BY(mLock);
+    std::thread mThread;
+    std::atomic<bool> mThreadStop = false;
+    std::condition_variable mCv;
+    std::mutex mCvLock;
+
+    bool isRequestPendingLocked(const void* clientId, int64_t requestId) const REQUIRES(mLock);
+
+    // Checks whether the requests in the pool has timed-out, run periodically in a separate thread.
+    void checkTimeout();
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_vhal_include_PendingRequestPool_H_
diff --git a/automotive/vehicle/aidl/impl/vhal/include/RecurrentTimer.h b/automotive/vehicle/aidl/impl/vhal/include/RecurrentTimer.h
new file mode 100644
index 0000000..5f0f716
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/include/RecurrentTimer.h
@@ -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.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_RecurrentTimer_H_
+#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_RecurrentTimer_H_
+
+#include <android-base/thread_annotations.h>
+
+#include <memory>
+#include <mutex>
+#include <queue>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// A thread-safe recurrent timer.
+class RecurrentTimer final {
+  public:
+    // The class for the function that would be called recurrently.
+    using Callback = std::function<void()>;
+
+    RecurrentTimer();
+
+    ~RecurrentTimer();
+
+    // Registers a recurrent callback for a given interval.
+    // Registering the same callback twice will override the interval provided before.
+    void registerTimerCallback(int64_t intervalInNano, std::shared_ptr<Callback> callback);
+
+    // Unregisters a previously registered recurrent callback.
+    void unregisterTimerCallback(std::shared_ptr<Callback> callback);
+
+  private:
+    // friend class for unit testing.
+    friend class RecurrentTimerTest;
+
+    struct CallbackInfo {
+        std::shared_ptr<Callback> callback;
+        int64_t interval;
+        int64_t nextTime;
+        // A flag to indicate whether this CallbackInfo is already outdated and should be ignored.
+        // The reason we need this flag is because we cannot easily remove an element from a heap.
+        bool outdated = false;
+
+        static bool cmp(const std::unique_ptr<CallbackInfo>& lhs,
+                        const std::unique_ptr<CallbackInfo>& rhs);
+    };
+
+    std::mutex mLock;
+    std::thread mThread;
+    std::condition_variable mCond;
+    bool mStopRequested GUARDED_BY(mLock) = false;
+    // A map to map each callback to its current active CallbackInfo in the mCallbackQueue.
+    std::unordered_map<std::shared_ptr<Callback>, CallbackInfo*> mCallbacks GUARDED_BY(mLock);
+    // A min-heap sorted by nextTime. Note that because we cannot remove arbitrary element from the
+    // heap, a single Callback can have multiple entries in this queue, all but one should be valid.
+    // The rest should be mark as outdated. The valid one is one stored in mCallbacks.
+    std::vector<std::unique_ptr<CallbackInfo>> mCallbackQueue GUARDED_BY(mLock);
+
+    void loop();
+
+    // Mark the callbackInfo as outdated and should be ignored when popped from the heap.
+    void markOutdatedLocked(CallbackInfo* callback) REQUIRES(mLock);
+    // Remove all outdated callbackInfos from the top of the heap. This function must be called
+    // each time we might introduce outdated elements to the top. We must make sure the heap is
+    // always valid from the top.
+    void removeInvalidCallbackLocked() REQUIRES(mLock);
+    // Pops the next closest callback (must be valid) from the heap.
+    std::unique_ptr<CallbackInfo> popNextCallbackLocked() REQUIRES(mLock);
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_vhal_include_RecurrentTimer_H_
diff --git a/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h b/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
new file mode 100644
index 0000000..28809c6
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.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.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_SubscriptionManager_H_
+#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_SubscriptionManager_H_
+
+#include "RecurrentTimer.h"
+
+#include <VehicleHalTypes.h>
+
+#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
+#include <android-base/result.h>
+#include <android-base/thread_annotations.h>
+
+#include <mutex>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// A thread-safe subscription manager that manages all VHAL subscriptions.
+class SubscriptionManager final {
+  public:
+    using CallbackType =
+            std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
+    using GetValueFunc = std::function<void(
+            const CallbackType& callback,
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value)>;
+
+    explicit SubscriptionManager(GetValueFunc&& action);
+    ~SubscriptionManager();
+
+    // Subscribes to properties according to {@code SubscribeOptions}. Note that all option must
+    // contain non-empty areaIds field, which contains all area IDs to subscribe. As a result,
+    // the options here is different from the options passed from VHAL client.
+    // Returns error if any of the subscribe options is not valid. If error is returned, no
+    // properties would be subscribed.
+    // Returns ok if all the options are parsed correctly and all the properties are subscribed.
+    ::android::base::Result<void> subscribe(
+            const CallbackType& callback,
+            const std::vector<::aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
+                    options,
+            bool isContinuousProperty);
+
+    // Unsubscribes from the properties for the callback.
+    // Returns error if the callback was not subscribed before or one of the given property was not
+    // subscribed. If error is returned, no property would be unsubscribed.
+    // Returns ok if all the requested properties for the callback are unsubscribed.
+    ::android::base::Result<void> unsubscribe(const CallbackType& callback,
+                                              const std::vector<int32_t>& propIds);
+
+    // Unsubscribes to all the properties for the callback.
+    // Returns error if the callback was not subscribed before. If error is returned, no property
+    // would be unsubscribed.
+    // Returns ok if all the properties for the callback are unsubscribed.
+    ::android::base::Result<void> unsubscribe(const CallbackType& callback);
+
+    // For a list of updated properties, returns a map that maps clients subscribing to
+    // the updated properties to a list of updated values. This would only return on-change property
+    // clients that should be informed for the given updated values.
+    std::unordered_map<
+            std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>,
+            std::vector<const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue*>>
+    getSubscribedClients(
+            const std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
+                    updatedValues);
+
+    // Checks whether the sample rate is valid.
+    static bool checkSampleRate(float sampleRate);
+
+  private:
+    struct PropIdAreaId {
+        int32_t propId;
+        int32_t areaId;
+
+        bool operator==(const PropIdAreaId& other) const;
+    };
+
+    struct PropIdAreaIdHash {
+        size_t operator()(const PropIdAreaId& propIdAreaId) const;
+    };
+
+    // A class to represent a registered subscription.
+    class Subscription {
+      public:
+        Subscription() = default;
+
+        Subscription(const Subscription&) = delete;
+
+        virtual ~Subscription() = default;
+
+        virtual bool isOnChange();
+    };
+
+    // A subscription for OnContinuous property. The registered action would be called recurrently
+    // until this class is destructed.
+    class RecurrentSubscription final : public Subscription {
+      public:
+        explicit RecurrentSubscription(std::shared_ptr<RecurrentTimer> timer,
+                                       std::function<void()>&& action, int64_t interval);
+        ~RecurrentSubscription();
+
+        bool isOnChange() override;
+
+      private:
+        std::shared_ptr<std::function<void()>> mAction;
+        std::shared_ptr<RecurrentTimer> mTimer;
+    };
+
+    // A subscription for OnChange property.
+    class OnChangeSubscription final : public Subscription {
+      public:
+        bool isOnChange() override;
+    };
+
+    mutable std::mutex mLock;
+    std::unordered_map<PropIdAreaId, std::unordered_set<CallbackType>, PropIdAreaIdHash>
+            mClientsByPropIdArea GUARDED_BY(mLock);
+    std::unordered_map<CallbackType, std::unordered_map<PropIdAreaId, std::unique_ptr<Subscription>,
+                                                        PropIdAreaIdHash>>
+            mSubscriptionsByClient GUARDED_BY(mLock);
+    // RecurrentTimer is thread-safe.
+    std::shared_ptr<RecurrentTimer> mTimer;
+    const GetValueFunc mGetValue;
+
+    static ::android::base::Result<int64_t> getInterval(float sampleRate);
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_vhal_include_SubscriptionManager_H_
diff --git a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
index 656dfaf..7d02a05 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
@@ -102,6 +102,53 @@
     sendGetOrSetValueResultsSeparately<ResultType, ResultsType>(callback, results);
 }
 
+// The timeout callback for GetValues/SetValues.
+template <class ResultType, class ResultsType>
+void onTimeout(
+        std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+        const std::unordered_set<int64_t>& timeoutIds) {
+    std::vector<ResultType> timeoutResults;
+    for (int64_t requestId : timeoutIds) {
+        ALOGD("hardware request timeout, request ID: %" PRId64, requestId);
+        timeoutResults.push_back({
+                .requestId = requestId,
+                .status = StatusCode::TRY_AGAIN,
+        });
+    }
+    sendGetOrSetValueResults<ResultType, ResultsType>(callback, timeoutResults);
+}
+
+// The on-results callback for GetValues/SetValues.
+template <class ResultType, class ResultsType>
+void getOrSetValuesCallback(
+        const void* clientId,
+        std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+        std::vector<ResultType> results, std::shared_ptr<PendingRequestPool> requestPool) {
+    std::unordered_set<int64_t> requestIds;
+    for (const auto& result : results) {
+        requestIds.insert(result.requestId);
+    }
+
+    auto finishedRequests = requestPool->tryFinishRequests(clientId, requestIds);
+
+    auto it = results.begin();
+    while (it != results.end()) {
+        int64_t requestId = it->requestId;
+        if (finishedRequests.find(requestId) == finishedRequests.end()) {
+            ALOGD("no pending request for the result from hardware, "
+                  "possibly already time-out, ID: %" PRId64,
+                  requestId);
+            it = results.erase(it);
+        } else {
+            it++;
+        }
+    }
+
+    if (!results.empty()) {
+        sendGetOrSetValueResults<ResultType, ResultsType>(callback, results);
+    }
+}
+
 // Specify the functions for GetValues and SetValues types.
 template void sendGetOrSetValueResult<GetValueResult, GetValueResults>(
         std::shared_ptr<IVehicleCallback> callback, const GetValueResult& result);
@@ -118,18 +165,55 @@
 template void sendGetOrSetValueResultsSeparately<SetValueResult, SetValueResults>(
         std::shared_ptr<IVehicleCallback> callback, const std::vector<SetValueResult>& results);
 
+template void onTimeout<GetValueResult, GetValueResults>(
+        std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+        const std::unordered_set<int64_t>& timeoutIds);
+template void onTimeout<SetValueResult, SetValueResults>(
+        std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+        const std::unordered_set<int64_t>& timeoutIds);
+
+template void getOrSetValuesCallback<GetValueResult, GetValueResults>(
+        const void* clientId,
+        std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+        std::vector<GetValueResult> results, std::shared_ptr<PendingRequestPool> requestPool);
+template void getOrSetValuesCallback<SetValueResult, SetValueResults>(
+        const void* clientId,
+        std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
+        std::vector<SetValueResult> results, std::shared_ptr<PendingRequestPool> requestPool);
+
 }  // namespace
 
-ConnectedClient::ConnectedClient(std::shared_ptr<IVehicleCallback> callback)
-    : mCallback(callback) {}
+ConnectedClient::ConnectedClient(std::shared_ptr<PendingRequestPool> requestPool,
+                                 std::shared_ptr<IVehicleCallback> callback)
+    : mRequestPool(requestPool), mCallback(callback) {}
+
+const void* ConnectedClient::id() {
+    return reinterpret_cast<const void*>(this);
+}
+
+Result<void> ConnectedClient::addRequests(const std::unordered_set<int64_t>& requestIds) {
+    return mRequestPool->addRequests(id(), requestIds, getTimeoutCallback());
+}
+
+std::unordered_set<int64_t> ConnectedClient::tryFinishRequests(
+        const std::unordered_set<int64_t>& requestIds) {
+    return mRequestPool->tryFinishRequests(id(), requestIds);
+}
 
 template <class ResultType, class ResultsType>
 GetSetValuesClient<ResultType, ResultsType>::GetSetValuesClient(
-        std::shared_ptr<IVehicleCallback> callback)
-    : ConnectedClient(callback) {
+        std::shared_ptr<PendingRequestPool> requestPool, std::shared_ptr<IVehicleCallback> callback)
+    : ConnectedClient(requestPool, callback) {
+    mTimeoutCallback = std::make_shared<const PendingRequestPool::TimeoutCallbackFunc>(
+            [callback](const std::unordered_set<int64_t>& timeoutIds) {
+                return onTimeout<ResultType, ResultsType>(callback, timeoutIds);
+            });
+    auto requestPoolCopy = mRequestPool;
+    const void* clientId = id();
     mResultCallback = std::make_shared<const std::function<void(std::vector<ResultType>)>>(
-            [callback](std::vector<ResultType> results) {
-                return sendGetOrSetValueResults<ResultType, ResultsType>(callback, results);
+            [clientId, callback, requestPoolCopy](std::vector<ResultType> results) {
+                return getOrSetValuesCallback<ResultType, ResultsType>(
+                        clientId, callback, std::move(results), requestPoolCopy);
             });
 }
 
@@ -140,6 +224,12 @@
 }
 
 template <class ResultType, class ResultsType>
+std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc>
+GetSetValuesClient<ResultType, ResultsType>::getTimeoutCallback() {
+    return mTimeoutCallback;
+}
+
+template <class ResultType, class ResultsType>
 void GetSetValuesClient<ResultType, ResultsType>::sendResults(
         const std::vector<ResultType>& results) {
     return sendGetOrSetValueResults<ResultType, ResultsType>(mCallback, results);
@@ -154,6 +244,93 @@
 template class GetSetValuesClient<GetValueResult, GetValueResults>;
 template class GetSetValuesClient<SetValueResult, SetValueResults>;
 
+SubscriptionClient::SubscriptionClient(std::shared_ptr<PendingRequestPool> requestPool,
+                                       std::shared_ptr<IVehicleCallback> callback)
+    : ConnectedClient(requestPool, callback) {
+    mTimeoutCallback = std::make_shared<const PendingRequestPool::TimeoutCallbackFunc>(
+            [](std::unordered_set<int64_t> timeoutIds) {
+                for (int64_t id : timeoutIds) {
+                    ALOGW("subscribe: requests with IDs: %" PRId64
+                          " has timed-out, not client informed, "
+                          "possibly one of recurrent requests for this subscription failed",
+                          id);
+                }
+            });
+    auto requestPoolCopy = mRequestPool;
+    const void* clientId = reinterpret_cast<const void*>(this);
+    mResultCallback = std::make_shared<const std::function<void(std::vector<GetValueResult>)>>(
+            [clientId, callback, requestPoolCopy](std::vector<GetValueResult> results) {
+                onGetValueResults(clientId, callback, requestPoolCopy, results);
+            });
+}
+
+std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>>
+SubscriptionClient::getResultCallback() {
+    return mResultCallback;
+}
+
+std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc>
+SubscriptionClient::getTimeoutCallback() {
+    return mTimeoutCallback;
+}
+
+void SubscriptionClient::onGetValueResults(const void* clientId,
+                                           std::shared_ptr<IVehicleCallback> callback,
+                                           std::shared_ptr<PendingRequestPool> requestPool,
+                                           std::vector<GetValueResult> results) {
+    std::unordered_set<int64_t> requestIds;
+    for (const auto& result : results) {
+        requestIds.insert(result.requestId);
+    }
+
+    auto finishedRequests = requestPool->tryFinishRequests(clientId, requestIds);
+    std::vector<VehiclePropValue> propValues;
+    for (auto& result : results) {
+        int64_t requestId = result.requestId;
+        if (finishedRequests.find(requestId) == finishedRequests.end()) {
+            ALOGE("subscribe[%" PRId64
+                  "]: no pending request for the result from hardware, "
+                  "possibly already time-out",
+                  requestId);
+            continue;
+        }
+        if (result.status != StatusCode::OK) {
+            ALOGE("subscribe[%" PRId64
+                  "]: hardware returns non-ok status for getValues, status: "
+                  "%d",
+                  requestId, toInt(result.status));
+            continue;
+        }
+        if (!result.prop.has_value()) {
+            ALOGE("subscribe[%" PRId64 "]: no prop value in getValues result", requestId);
+            continue;
+        }
+        propValues.push_back(std::move(result.prop.value()));
+    }
+
+    if (propValues.empty()) {
+        return;
+    }
+    // TODO(b/205189110): Use memory pool here and fill in sharedMemoryId.
+    VehiclePropValues vehiclePropValues;
+    int32_t sharedMemoryFileCount = 0;
+    ScopedAStatus status = vectorToStableLargeParcelable(propValues, &vehiclePropValues);
+    if (!status.isOk()) {
+        int statusCode = status.getServiceSpecificError();
+        ALOGE("failed to marshal result into large parcelable, error: "
+              "%s, code: %d",
+              status.getMessage(), statusCode);
+        return;
+    }
+
+    if (ScopedAStatus callbackStatus =
+                callback->onPropertyEvent(vehiclePropValues, sharedMemoryFileCount);
+        !callbackStatus.isOk()) {
+        ALOGE("failed to call callback, error: %s, code: %d", status.getMessage(),
+              status.getServiceSpecificError());
+    }
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index e98f021..1e76eb7 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -25,11 +25,17 @@
 #include <android-base/result.h>
 #include <utils/Log.h>
 
+#include <inttypes.h>
+#include <set>
+#include <unordered_set>
+
 namespace android {
 namespace hardware {
 namespace automotive {
 namespace vehicle {
 
+namespace {
+
 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
 using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
@@ -51,13 +57,29 @@
 using ::android::base::Result;
 using ::ndk::ScopedAStatus;
 
+std::string toString(const std::unordered_set<int64_t>& values) {
+    std::string str = "";
+    for (auto it = values.begin(); it != values.end(); it++) {
+        str += std::to_string(*it);
+        if (std::next(it, 1) != values.end()) {
+            str += ", ";
+        }
+    }
+    return str;
+}
+
+}  // namespace
+
 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware)
-    : mVehicleHardware(std::move(hardware)) {
+    : mVehicleHardware(std::move(hardware)),
+      mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)) {
     auto configs = mVehicleHardware->getAllPropertyConfigs();
     for (auto& config : configs) {
         mConfigsByPropId[config.prop] = config;
     }
-    auto result = LargeParcelableBase::parcelableVectorToStableLargeParcelable(configs);
+    VehiclePropConfigs vehiclePropConfigs;
+    vehiclePropConfigs.payloads = std::move(configs);
+    auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
     if (!result.ok()) {
         ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
               getErrorMsg(result).c_str(), getIntErrorCode(result));
@@ -67,10 +89,81 @@
     if (result.value() != nullptr) {
         mConfigFile = std::move(result.value());
     }
+
+    mSubscriptionManager = std::make_unique<SubscriptionManager>(
+            [this](const CallbackType& callback, const VehiclePropValue& value) {
+                getValueFromHardwareCallCallback(callback, value);
+            });
+}
+
+DefaultVehicleHal::~DefaultVehicleHal() {
+    // mSubscriptionManager has reference to this, so must be destroyed before other members.
+    mSubscriptionManager.reset();
+}
+
+template <class T>
+std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
+        std::unordered_map<CallbackType, std::shared_ptr<T>>* clients,
+        const CallbackType& callback) {
+    if (clients->find(callback) == clients->end()) {
+        // TODO(b/204943359): Remove client from clients when linkToDeath is implemented.
+        (*clients)[callback] = std::make_shared<T>(mPendingRequestPool, callback);
+    }
+    return (*clients)[callback];
+}
+
+template std::shared_ptr<DefaultVehicleHal::GetValuesClient>
+DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::GetValuesClient>(
+        std::unordered_map<CallbackType, std::shared_ptr<GetValuesClient>>* clients,
+        const CallbackType& callback);
+template std::shared_ptr<DefaultVehicleHal::SetValuesClient>
+DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::SetValuesClient>(
+        std::unordered_map<CallbackType, std::shared_ptr<SetValuesClient>>* clients,
+        const CallbackType& callback);
+template std::shared_ptr<SubscriptionClient>
+DefaultVehicleHal::getOrCreateClient<SubscriptionClient>(
+        std::unordered_map<CallbackType, std::shared_ptr<SubscriptionClient>>* clients,
+        const CallbackType& callback);
+
+void DefaultVehicleHal::getValueFromHardwareCallCallback(const CallbackType& callback,
+                                                         const VehiclePropValue& value) {
+    int64_t subscribeId;
+    std::shared_ptr<SubscriptionClient> client;
+    {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+        // This is initialized to 0 if callback does not exist in the map.
+        subscribeId = (mSubscribeIdByClient[callback])++;
+        client = getOrCreateClient(&mSubscriptionClients, callback);
+    }
+    if (auto addRequestResult = client->addRequests({subscribeId}); !addRequestResult.ok()) {
+        ALOGE("subscribe[%" PRId64 "]: too many pending requests, ignore the getValue request",
+              subscribeId);
+        return;
+    }
+
+    std::vector<GetValueRequest> hardwareRequests = {{
+            .requestId = subscribeId,
+            .prop = value,
+    }};
+
+    if (StatusCode status =
+                mVehicleHardware->getValues(client->getResultCallback(), hardwareRequests);
+        status != StatusCode::OK) {
+        // If the hardware returns error, finish all the pending requests for this request because
+        // we never expect hardware to call callback for these requests.
+        client->tryFinishRequests({subscribeId});
+        ALOGE("subscribe[%" PRId64 "]: failed to get value from VehicleHardware, code: %d",
+              subscribeId, toInt(status));
+    }
+}
+
+void DefaultVehicleHal::setTimeout(int64_t timeoutInNano) {
+    mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
 }
 
 ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
     if (mConfigFile != nullptr) {
+        output->payloads.clear();
         output->sharedMemoryFd.set(dup(mConfigFile->get()));
         return ScopedAStatus::ok();
     }
@@ -81,27 +174,6 @@
     return ScopedAStatus::ok();
 }
 
-template <class T>
-std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
-        std::unordered_map<CallbackType, std::shared_ptr<T>>* clients,
-        const CallbackType& callback) {
-    if (clients->find(callback) == clients->end()) {
-        // TODO(b/204943359): Remove client from clients when linkToDeath is implemented.
-        (*clients)[callback] = std::make_shared<T>(callback);
-    }
-    return (*clients)[callback];
-}
-
-template std::shared_ptr<DefaultVehicleHal::GetValuesClient>
-DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::GetValuesClient>(
-        std::unordered_map<CallbackType, std::shared_ptr<GetValuesClient>>* clients,
-        const CallbackType& callback);
-
-template std::shared_ptr<DefaultVehicleHal::SetValuesClient>
-DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::SetValuesClient>(
-        std::unordered_map<CallbackType, std::shared_ptr<SetValuesClient>>* clients,
-        const CallbackType& callback);
-
 Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) {
     int32_t propId = propValue.prop;
     auto it = mConfigsByPropId.find(propId);
@@ -129,89 +201,119 @@
 
 ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback,
                                            const GetValueRequests& requests) {
-    // TODO(b/203713317): check for duplicate properties and duplicate request IDs.
-
-    const std::vector<GetValueRequest>* getValueRequests;
-    // Define deserializedResults here because we need it to have the same lifetime as
-    // getValueRequests.
-    expected<std::vector<GetValueRequest>, ScopedAStatus> deserializedResults;
-    if (!requests.payloads.empty()) {
-        getValueRequests = &requests.payloads;
-    } else {
-        deserializedResults = stableLargeParcelableToVector<GetValueRequest>(requests);
-        if (!deserializedResults.ok()) {
-            ALOGE("failed to parse getValues requests");
-            return std::move(deserializedResults.error());
-        }
-        getValueRequests = &deserializedResults.value();
+    expected<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus>
+            deserializedResults = fromStableLargeParcelable(requests);
+    if (!deserializedResults.ok()) {
+        ALOGE("getValues: failed to parse getValues requests");
+        return std::move(deserializedResults.error());
     }
+    const std::vector<GetValueRequest>& getValueRequests =
+            deserializedResults.value().getObject()->payloads;
+
+    auto maybeRequestIds = checkDuplicateRequests(getValueRequests);
+    if (!maybeRequestIds.ok()) {
+        ALOGE("getValues: duplicate request ID");
+        return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
+    }
+    // The set of request Ids that we would send to hardware.
+    std::unordered_set<int64_t> hardwareRequestIds(maybeRequestIds.value().begin(),
+                                                   maybeRequestIds.value().end());
 
     std::shared_ptr<GetValuesClient> client;
     {
         std::scoped_lock<std::mutex> lockGuard(mLock);
         client = getOrCreateClient(&mGetValuesClients, callback);
     }
+    // Register the pending hardware requests and also check for duplicate request Ids.
+    if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
+        ALOGE("getValues[%s]: failed to add pending requests, error: %s",
+              toString(hardwareRequestIds).c_str(), addRequestResult.error().message().c_str());
+        return toScopedAStatus(addRequestResult);
+    }
 
     if (StatusCode status =
-                mVehicleHardware->getValues(client->getResultCallback(), *getValueRequests);
+                mVehicleHardware->getValues(client->getResultCallback(), getValueRequests);
         status != StatusCode::OK) {
+        // If the hardware returns error, finish all the pending requests for this request because
+        // we never expect hardware to call callback for these requests.
+        client->tryFinishRequests(hardwareRequestIds);
+        ALOGE("getValues[%s]: failed to get value from VehicleHardware, status: %d",
+              toString(hardwareRequestIds).c_str(), toInt(status));
         return ScopedAStatus::fromServiceSpecificErrorWithMessage(
                 toInt(status), "failed to get value from VehicleHardware");
     }
-
     return ScopedAStatus::ok();
 }
 
 ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
                                            const SetValueRequests& requests) {
-    // TODO(b/203713317): check for duplicate properties and duplicate request IDs.
-
-    const std::vector<SetValueRequest>* setValueRequests;
-    // Define deserializedResults here because we need it to have the same lifetime as
-    // setValueRequests.
-    expected<std::vector<SetValueRequest>, ScopedAStatus> deserializedResults;
-    if (!requests.payloads.empty()) {
-        setValueRequests = &requests.payloads;
-    } else {
-        deserializedResults = stableLargeParcelableToVector<SetValueRequest>(requests);
-        if (!deserializedResults.ok()) {
-            ALOGE("failed to parse setValues requests");
-            return std::move(deserializedResults.error());
-        }
-        setValueRequests = &deserializedResults.value();
+    expected<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
+            deserializedResults = fromStableLargeParcelable(requests);
+    if (!deserializedResults.ok()) {
+        ALOGE("setValues: failed to parse setValues requests");
+        return std::move(deserializedResults.error());
     }
+    const std::vector<SetValueRequest>& setValueRequests =
+            deserializedResults.value().getObject()->payloads;
 
     // A list of failed result we already know before sending to hardware.
     std::vector<SetValueResult> failedResults;
     // The list of requests that we would send to hardware.
     std::vector<SetValueRequest> hardwareRequests;
 
-    for (auto& request : *setValueRequests) {
+    auto maybeRequestIds = checkDuplicateRequests(setValueRequests);
+    if (!maybeRequestIds.ok()) {
+        ALOGE("setValues: duplicate request ID");
+        return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
+    }
+
+    for (auto& request : setValueRequests) {
         int64_t requestId = request.requestId;
         if (auto result = checkProperty(request.value); !result.ok()) {
-            ALOGW("property not valid: %s", result.error().message().c_str());
+            ALOGW("setValues[%" PRId64 "]: property not valid: %s", requestId,
+                  result.error().message().c_str());
             failedResults.push_back(SetValueResult{
                     .requestId = requestId,
                     .status = StatusCode::INVALID_ARG,
             });
             continue;
         }
+
         hardwareRequests.push_back(request);
     }
 
+    // The set of request Ids that we would send to hardware.
+    std::unordered_set<int64_t> hardwareRequestIds;
+    for (const auto& request : hardwareRequests) {
+        hardwareRequestIds.insert(request.requestId);
+    }
+
     std::shared_ptr<SetValuesClient> client;
     {
         std::scoped_lock<std::mutex> lockGuard(mLock);
         client = getOrCreateClient(&mSetValuesClients, callback);
     }
 
+    // Register the pending hardware requests and also check for duplicate request Ids.
+    if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
+        ALOGE("setValues[%s], failed to add pending requests, error: %s",
+              toString(hardwareRequestIds).c_str(), addRequestResult.error().message().c_str());
+        return toScopedAStatus(addRequestResult, StatusCode::INVALID_ARG);
+    }
+
     if (!failedResults.empty()) {
+        // First send the failed results we already know back to the client.
         client->sendResults(failedResults);
     }
 
     if (StatusCode status =
                 mVehicleHardware->setValues(client->getResultCallback(), hardwareRequests);
         status != StatusCode::OK) {
+        // If the hardware returns error, finish all the pending requests for this request because
+        // we never expect hardware to call callback for these requests.
+        client->tryFinishRequests(hardwareRequestIds);
+        ALOGE("setValues[%s], failed to set value to VehicleHardware, status: %d",
+              toString(hardwareRequestIds).c_str(), toInt(status));
         return ScopedAStatus::fromServiceSpecificErrorWithMessage(
                 toInt(status), "failed to set value to VehicleHardware");
     }
@@ -219,6 +321,34 @@
     return ScopedAStatus::ok();
 }
 
+#define CHECK_DUPLICATE_REQUESTS(PROP_NAME)                                                      \
+    do {                                                                                         \
+        std::vector<int64_t> requestIds;                                                         \
+        std::set<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> requestProps; \
+        for (const auto& request : requests) {                                                   \
+            const auto& prop = request.PROP_NAME;                                                \
+            if (requestProps.count(prop) != 0) {                                                 \
+                return ::android::base::Error()                                                  \
+                       << "duplicate request for property: " << prop.toString();                 \
+            }                                                                                    \
+            requestProps.insert(prop);                                                           \
+            requestIds.push_back(request.requestId);                                             \
+        }                                                                                        \
+        return requestIds;                                                                       \
+    } while (0);
+
+::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
+        const std::vector<GetValueRequest>& requests) {
+    CHECK_DUPLICATE_REQUESTS(prop);
+}
+
+::android::base::Result<std::vector<int64_t>> DefaultVehicleHal::checkDuplicateRequests(
+        const std::vector<SetValueRequest>& requests) {
+    CHECK_DUPLICATE_REQUESTS(value);
+}
+
+#undef CHECK_DUPLICATE_REQUESTS
+
 ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
                                                 VehiclePropConfigs* output) {
     std::vector<VehiclePropConfig> configs;
@@ -232,12 +362,10 @@
 
 ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType&,
                                            const std::vector<SubscribeOptions>&, int32_t) {
-    // TODO(b/200737967): implement this.
     return ScopedAStatus::ok();
 }
 
 ScopedAStatus DefaultVehicleHal::unsubscribe(const CallbackType&, const std::vector<int32_t>&) {
-    // TODO(b/200737967): implement this.
     return ScopedAStatus::ok();
 }
 
diff --git a/automotive/vehicle/aidl/impl/vhal/src/PendingRequestPool.cpp b/automotive/vehicle/aidl/impl/vhal/src/PendingRequestPool.cpp
new file mode 100644
index 0000000..23a5403
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/src/PendingRequestPool.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "PendingRequestPool.h"
+
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::android::base::Error;
+using ::android::base::Result;
+
+// At least check every 1s.
+constexpr int64_t CHECK_TIME_IN_NANO = 1000000000;
+
+}  // namespace
+
+PendingRequestPool::PendingRequestPool(int64_t timeoutInNano)
+    : mTimeoutInNano(timeoutInNano), mThread([this] {
+          // [this] must be alive within this thread because destructor would wait for this thread
+          // to exit.
+          int64_t sleepTime = std::min(mTimeoutInNano, static_cast<int64_t>(CHECK_TIME_IN_NANO));
+          std::unique_lock<std::mutex> lk(mCvLock);
+          while (!mCv.wait_for(lk, std::chrono::nanoseconds(sleepTime),
+                               [this] { return mThreadStop.load(); })) {
+              checkTimeout();
+          }
+      }) {}
+
+PendingRequestPool::~PendingRequestPool() {
+    mThreadStop = true;
+    mCv.notify_all();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+
+    // If this pool is being destructed, send out all pending requests as timeout.
+    {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+
+        for (auto& [_, pendingRequests] : mPendingRequestsByClient) {
+            for (const auto& request : pendingRequests) {
+                (*request.callback)(request.requestIds);
+            }
+        }
+        mPendingRequestsByClient.clear();
+    }
+}
+
+Result<void> PendingRequestPool::addRequests(const void* clientId,
+                                             const std::unordered_set<int64_t>& requestIds,
+                                             std::shared_ptr<const TimeoutCallbackFunc> callback) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    std::list<PendingRequest>* pendingRequests;
+    size_t pendingRequestCount = 0;
+    if (mPendingRequestsByClient.find(clientId) != mPendingRequestsByClient.end()) {
+        pendingRequests = &mPendingRequestsByClient[clientId];
+        for (const auto& pendingRequest : *pendingRequests) {
+            const auto& pendingRequestIds = pendingRequest.requestIds;
+            for (int64_t requestId : requestIds) {
+                if (pendingRequestIds.find(requestId) != pendingRequestIds.end()) {
+                    return Error(toInt(StatusCode::INVALID_ARG))
+                           << "duplicate request ID: " << requestId;
+                }
+            }
+            pendingRequestCount += pendingRequestIds.size();
+        }
+    } else {
+        // Create a new empty list for this client.
+        pendingRequests = &mPendingRequestsByClient[clientId];
+    }
+
+    if (requestIds.size() > MAX_PENDING_REQUEST_PER_CLIENT - pendingRequestCount) {
+        return Error(toInt(StatusCode::TRY_AGAIN)) << "too many pending requests";
+    }
+
+    int64_t currentTime = elapsedRealtimeNano();
+    int64_t timeoutTimestamp = currentTime + mTimeoutInNano;
+
+    pendingRequests->push_back({
+            .requestIds = std::unordered_set<int64_t>(requestIds.begin(), requestIds.end()),
+            .timeoutTimestamp = timeoutTimestamp,
+            .callback = callback,
+    });
+
+    return {};
+}
+
+bool PendingRequestPool::isRequestPending(const void* clientId, int64_t requestId) const {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    return isRequestPendingLocked(clientId, requestId);
+}
+
+size_t PendingRequestPool::countPendingRequests() const {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    size_t count = 0;
+    for (const auto& [clientId, requests] : mPendingRequestsByClient) {
+        for (const auto& request : requests) {
+            count += request.requestIds.size();
+        }
+    }
+    return count;
+}
+
+size_t PendingRequestPool::countPendingRequests(const void* clientId) const {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    auto it = mPendingRequestsByClient.find(clientId);
+    if (it == mPendingRequestsByClient.end()) {
+        return 0;
+    }
+
+    size_t count = 0;
+    for (const auto& pendingRequest : it->second) {
+        count += pendingRequest.requestIds.size();
+    }
+
+    return count;
+}
+
+bool PendingRequestPool::isRequestPendingLocked(const void* clientId, int64_t requestId) const {
+    auto it = mPendingRequestsByClient.find(clientId);
+    if (it == mPendingRequestsByClient.end()) {
+        return false;
+    }
+    for (const auto& pendingRequest : it->second) {
+        const auto& requestIds = pendingRequest.requestIds;
+        if (requestIds.find(requestId) != requestIds.end()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void PendingRequestPool::checkTimeout() {
+    std::vector<PendingRequest> timeoutRequests;
+    {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+
+        int64_t currentTime = elapsedRealtimeNano();
+
+        std::vector<const void*> clientsWithEmptyRequests;
+
+        for (auto& [clientId, pendingRequests] : mPendingRequestsByClient) {
+            auto it = pendingRequests.begin();
+            while (it != pendingRequests.end()) {
+                if (it->timeoutTimestamp >= currentTime) {
+                    break;
+                }
+                timeoutRequests.push_back(std::move(*it));
+                it = pendingRequests.erase(it);
+            }
+
+            if (pendingRequests.empty()) {
+                clientsWithEmptyRequests.push_back(clientId);
+            }
+        }
+
+        for (const void* clientId : clientsWithEmptyRequests) {
+            mPendingRequestsByClient.erase(clientId);
+        }
+    }
+
+    // Call the callback outside the lock.
+    for (const auto& request : timeoutRequests) {
+        (*request.callback)(request.requestIds);
+    }
+}
+
+std::unordered_set<int64_t> PendingRequestPool::tryFinishRequests(
+        const void* clientId, const std::unordered_set<int64_t>& requestIds) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    std::unordered_set<int64_t> foundIds;
+
+    if (mPendingRequestsByClient.find(clientId) == mPendingRequestsByClient.end()) {
+        return foundIds;
+    }
+
+    auto& pendingRequests = mPendingRequestsByClient[clientId];
+    auto it = pendingRequests.begin();
+    while (it != pendingRequests.end()) {
+        auto& pendingRequestIds = it->requestIds;
+        for (int64_t requestId : requestIds) {
+            auto idIt = pendingRequestIds.find(requestId);
+            if (idIt == pendingRequestIds.end()) {
+                continue;
+            }
+            pendingRequestIds.erase(idIt);
+            foundIds.insert(requestId);
+        }
+        if (pendingRequestIds.empty()) {
+            it = pendingRequests.erase(it);
+            continue;
+        }
+        it++;
+    }
+
+    return foundIds;
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/vhal/src/RecurrentTimer.cpp b/automotive/vehicle/aidl/impl/vhal/src/RecurrentTimer.cpp
new file mode 100644
index 0000000..8521c4d
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/src/RecurrentTimer.cpp
@@ -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.
+ */
+
+#include "RecurrentTimer.h"
+
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+#include <inttypes.h>
+#include <math.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::android::base::ScopedLockAssertion;
+
+RecurrentTimer::RecurrentTimer() : mThread(&RecurrentTimer::loop, this) {}
+
+RecurrentTimer::~RecurrentTimer() {
+    {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+        mStopRequested = true;
+    }
+    mCond.notify_one();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+void RecurrentTimer::registerTimerCallback(int64_t intervalInNano,
+                                           std::shared_ptr<RecurrentTimer::Callback> callback) {
+    {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+
+        // Aligns the nextTime to multiply of interval.
+        int64_t nextTime = ceil(elapsedRealtimeNano() / intervalInNano) * intervalInNano;
+
+        std::unique_ptr<CallbackInfo> info = std::make_unique<CallbackInfo>();
+        info->callback = callback;
+        info->interval = intervalInNano;
+        info->nextTime = nextTime;
+
+        auto it = mCallbacks.find(callback);
+        if (it != mCallbacks.end()) {
+            ALOGI("Replacing an existing timer callback with a new interval, current: %" PRId64
+                  " ns, new: %" PRId64 " ns",
+                  it->second->interval, intervalInNano);
+            markOutdatedLocked(it->second);
+        }
+        mCallbacks[callback] = info.get();
+        mCallbackQueue.push_back(std::move(info));
+        // Insert the last element into the heap.
+        std::push_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp);
+    }
+    mCond.notify_one();
+}
+
+void RecurrentTimer::unregisterTimerCallback(std::shared_ptr<RecurrentTimer::Callback> callback) {
+    {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+
+        auto it = mCallbacks.find(callback);
+        if (it == mCallbacks.end()) {
+            ALOGE("No event found to unregister");
+            return;
+        }
+
+        markOutdatedLocked(it->second);
+        mCallbacks.erase(it);
+    }
+
+    mCond.notify_one();
+}
+
+void RecurrentTimer::markOutdatedLocked(RecurrentTimer::CallbackInfo* info) {
+    info->outdated = true;
+    info->callback = nullptr;
+    // Make sure the first element is always valid.
+    removeInvalidCallbackLocked();
+}
+
+void RecurrentTimer::removeInvalidCallbackLocked() {
+    while (mCallbackQueue.size() != 0 && mCallbackQueue[0]->outdated) {
+        std::pop_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp);
+        mCallbackQueue.pop_back();
+    }
+}
+
+std::unique_ptr<RecurrentTimer::CallbackInfo> RecurrentTimer::popNextCallbackLocked() {
+    std::pop_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp);
+    std::unique_ptr<CallbackInfo> info = std::move(mCallbackQueue[mCallbackQueue.size() - 1]);
+    mCallbackQueue.pop_back();
+    // Make sure the first element is always valid.
+    removeInvalidCallbackLocked();
+    return info;
+}
+
+void RecurrentTimer::loop() {
+    std::unique_lock<std::mutex> uniqueLock(mLock);
+
+    while (true) {
+        // Wait until the timer exits or we have at least one recurrent callback.
+        mCond.wait(uniqueLock, [this] {
+            ScopedLockAssertion lockAssertion(mLock);
+            return mStopRequested || mCallbackQueue.size() != 0;
+        });
+
+        int64_t interval;
+        {
+            ScopedLockAssertion lockAssertion(mLock);
+            if (mStopRequested) {
+                return;
+            }
+            // The first element is the nearest next event.
+            int64_t nextTime = mCallbackQueue[0]->nextTime;
+            int64_t now = elapsedRealtimeNano();
+            if (nextTime > now) {
+                interval = nextTime - now;
+            } else {
+                interval = 0;
+            }
+        }
+
+        // Wait for the next event or the timer exits.
+        if (mCond.wait_for(uniqueLock, std::chrono::nanoseconds(interval), [this] {
+                ScopedLockAssertion lockAssertion(mLock);
+                return mStopRequested;
+            })) {
+            return;
+        }
+
+        {
+            ScopedLockAssertion lockAssertion(mLock);
+            int64_t now = elapsedRealtimeNano();
+            while (mCallbackQueue.size() > 0) {
+                int64_t nextTime = mCallbackQueue[0]->nextTime;
+                if (nextTime > now) {
+                    break;
+                }
+
+                std::unique_ptr<CallbackInfo> info = popNextCallbackLocked();
+                info->nextTime += info->interval;
+
+                auto callback = info->callback;
+                mCallbackQueue.push_back(std::move(info));
+                std::push_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp);
+
+                (*callback)();
+            }
+        }
+    }
+}
+
+bool RecurrentTimer::CallbackInfo::cmp(const std::unique_ptr<RecurrentTimer::CallbackInfo>& lhs,
+                                       const std::unique_ptr<RecurrentTimer::CallbackInfo>& rhs) {
+    return lhs->nextTime > rhs->nextTime;
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
new file mode 100644
index 0000000..dc9a6ce
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SubscriptionManager.h"
+
+#include <math/HashCombine.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace {
+
+constexpr float ONE_SECOND_IN_NANO = 1000000000.;
+
+}  // namespace
+
+using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
+using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::android::base::Error;
+using ::android::base::Result;
+using ::ndk::ScopedAStatus;
+
+bool SubscriptionManager::PropIdAreaId::operator==(const PropIdAreaId& other) const {
+    return areaId == other.areaId && propId == other.propId;
+}
+
+size_t SubscriptionManager::PropIdAreaIdHash::operator()(PropIdAreaId const& propIdAreaId) const {
+    size_t res = 0;
+    hashCombine(res, propIdAreaId.propId);
+    hashCombine(res, propIdAreaId.areaId);
+    return res;
+}
+
+SubscriptionManager::SubscriptionManager(GetValueFunc&& action)
+    : mTimer(std::make_shared<RecurrentTimer>()), mGetValue(std::move(action)) {}
+
+SubscriptionManager::~SubscriptionManager() {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    mClientsByPropIdArea.clear();
+    mSubscriptionsByClient.clear();
+}
+
+bool SubscriptionManager::checkSampleRate(float sampleRate) {
+    return getInterval(sampleRate).ok();
+}
+
+Result<int64_t> SubscriptionManager::getInterval(float sampleRate) {
+    int64_t interval = 0;
+    if (sampleRate <= 0) {
+        return Error() << "invalid sample rate, must be a positive number";
+    }
+    if (sampleRate <= (ONE_SECOND_IN_NANO / static_cast<float>(INT64_MAX))) {
+        return Error() << "invalid sample rate: " << sampleRate << ", too small";
+    }
+    interval = static_cast<int64_t>(ONE_SECOND_IN_NANO / sampleRate);
+    return interval;
+}
+
+Result<void> SubscriptionManager::subscribe(const std::shared_ptr<IVehicleCallback>& callback,
+                                            const std::vector<SubscribeOptions>& options,
+                                            bool isContinuousProperty) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    std::vector<int64_t> intervals;
+
+    for (const auto& option : options) {
+        float sampleRate = option.sampleRate;
+
+        if (isContinuousProperty) {
+            auto intervalResult = getInterval(sampleRate);
+            if (!intervalResult.ok()) {
+                return intervalResult.error();
+            }
+            intervals.push_back(intervalResult.value());
+        }
+
+        if (option.areaIds.empty()) {
+            ALOGE("area IDs to subscribe must not be empty");
+            return Error() << "area IDs to subscribe must not be empty";
+        }
+    }
+
+    size_t intervalIndex = 0;
+    for (const auto& option : options) {
+        int32_t propId = option.propId;
+        const std::vector<int32_t>& areaIds = option.areaIds;
+        int64_t interval = 0;
+        if (isContinuousProperty) {
+            interval = intervals[intervalIndex];
+            intervalIndex++;
+        }
+        for (int32_t areaId : areaIds) {
+            PropIdAreaId propIdAreaId = {
+                    .propId = propId,
+                    .areaId = areaId,
+            };
+            if (isContinuousProperty) {
+                VehiclePropValue propValueRequest{
+                        .prop = propId,
+                        .areaId = areaId,
+                };
+                mSubscriptionsByClient[callback][propIdAreaId] =
+                        std::make_unique<RecurrentSubscription>(
+                                mTimer,
+                                [this, callback, propValueRequest] {
+                                    mGetValue(callback, propValueRequest);
+                                },
+                                interval);
+            } else {
+                mSubscriptionsByClient[callback][propIdAreaId] =
+                        std::make_unique<OnChangeSubscription>();
+            }
+            mClientsByPropIdArea[propIdAreaId].insert(callback);
+        }
+    }
+    return {};
+}
+
+Result<void> SubscriptionManager::unsubscribe(const std::shared_ptr<IVehicleCallback>& callback,
+                                              const std::vector<int32_t>& propIds) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    if (mSubscriptionsByClient.find(callback) == mSubscriptionsByClient.end()) {
+        return Error() << "No property was subscribed for the callback";
+    }
+    std::unordered_set<int32_t> subscribedPropIds;
+    for (auto const& [propIdAreaId, _] : mSubscriptionsByClient[callback]) {
+        subscribedPropIds.insert(propIdAreaId.propId);
+    }
+
+    for (int32_t propId : propIds) {
+        if (subscribedPropIds.find(propId) == subscribedPropIds.end()) {
+            return Error() << "property ID: " << propId << " is not subscribed";
+        }
+    }
+
+    auto& subscriptions = mSubscriptionsByClient[callback];
+    auto it = subscriptions.begin();
+    while (it != subscriptions.end()) {
+        int32_t propId = it->first.propId;
+        if (std::find(propIds.begin(), propIds.end(), propId) != propIds.end()) {
+            auto& clients = mClientsByPropIdArea[it->first];
+            clients.erase(callback);
+            if (clients.empty()) {
+                mClientsByPropIdArea.erase(it->first);
+            }
+            it = subscriptions.erase(it);
+        } else {
+            it++;
+        }
+    }
+    if (subscriptions.empty()) {
+        mSubscriptionsByClient.erase(callback);
+    }
+    return {};
+}
+
+Result<void> SubscriptionManager::unsubscribe(const std::shared_ptr<IVehicleCallback>& callback) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    if (mSubscriptionsByClient.find(callback) == mSubscriptionsByClient.end()) {
+        return Error() << "No property was subscribed for the callback";
+    }
+
+    auto& subscriptions = mSubscriptionsByClient[callback];
+    for (auto const& [propIdAreaId, _] : subscriptions) {
+        auto& clients = mClientsByPropIdArea[propIdAreaId];
+        clients.erase(callback);
+        if (clients.empty()) {
+            mClientsByPropIdArea.erase(propIdAreaId);
+        }
+    }
+    mSubscriptionsByClient.erase(callback);
+    return {};
+}
+
+std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<const VehiclePropValue*>>
+SubscriptionManager::getSubscribedClients(const std::vector<VehiclePropValue>& updatedValues) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<const VehiclePropValue*>>
+            clients;
+
+    for (const auto& value : updatedValues) {
+        PropIdAreaId propIdAreaId{
+                .propId = value.prop,
+                .areaId = value.areaId,
+        };
+        if (mClientsByPropIdArea.find(propIdAreaId) == mClientsByPropIdArea.end()) {
+            continue;
+        }
+        for (const auto& client : mClientsByPropIdArea[propIdAreaId]) {
+            if (!mSubscriptionsByClient[client][propIdAreaId]->isOnChange()) {
+                continue;
+            }
+            clients[client].push_back(&value);
+        }
+    }
+    return clients;
+}
+
+SubscriptionManager::RecurrentSubscription::RecurrentSubscription(
+        std::shared_ptr<RecurrentTimer> timer, std::function<void()>&& action, int64_t interval)
+    : mAction(std::make_shared<std::function<void()>>(action)), mTimer(timer) {
+    mTimer->registerTimerCallback(interval, mAction);
+}
+
+SubscriptionManager::RecurrentSubscription::~RecurrentSubscription() {
+    mTimer->unregisterTimerCallback(mAction);
+}
+
+bool SubscriptionManager::RecurrentSubscription::isOnChange() {
+    return false;
+}
+
+bool SubscriptionManager::OnChangeSubscription::isOnChange() {
+    return true;
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp
index ddd0c65..bd4a565 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp
@@ -39,12 +39,17 @@
     void SetUp() override {
         mCallback = ndk::SharedRefBase::make<MockVehicleCallback>();
         mCallbackClient = IVehicleCallback::fromBinder(mCallback->asBinder());
+        // timeout: 1s.
+        int64_t timeout = 1000000000;
+        mPool = std::make_shared<PendingRequestPool>(timeout);
     }
 
     std::shared_ptr<IVehicleCallback> getCallbackClient() { return mCallbackClient; }
 
     MockVehicleCallback* getCallback() { return mCallback.get(); }
 
+    std::shared_ptr<PendingRequestPool> getPool() { return mPool; }
+
   protected:
     using GetValuesClient = GetSetValuesClient<GetValueResult, GetValueResults>;
     using SetValuesClient = GetSetValuesClient<SetValueResult, SetValueResults>;
@@ -52,6 +57,7 @@
   private:
     std::shared_ptr<MockVehicleCallback> mCallback;
     std::shared_ptr<IVehicleCallback> mCallbackClient;
+    std::shared_ptr<PendingRequestPool> mPool;
 };
 
 TEST_F(ConnectedClientTest, testSendGetValueResults) {
@@ -72,7 +78,7 @@
                                                            },
                                            }};
 
-    GetValuesClient client(getCallbackClient());
+    GetValuesClient client(getPool(), getCallbackClient());
 
     client.sendResults(results);
 
@@ -99,7 +105,7 @@
                                                            },
                                            }};
 
-    GetValuesClient client(getCallbackClient());
+    GetValuesClient client(getPool(), getCallbackClient());
 
     client.sendResultsSeparately(results);
 
@@ -131,7 +137,9 @@
                                                            },
                                            }};
 
-    GetValuesClient client(getCallbackClient());
+    GetValuesClient client(getPool(), getCallbackClient());
+
+    client.addRequests({0, 1});
 
     (*(client.getResultCallback()))(results);
 
@@ -150,7 +158,7 @@
                                                    .status = StatusCode::OK,
                                            }};
 
-    SetValuesClient client(getCallbackClient());
+    SetValuesClient client(getPool(), getCallbackClient());
 
     client.sendResults(results);
 
@@ -169,7 +177,7 @@
                                                    .status = StatusCode::OK,
                                            }};
 
-    SetValuesClient client(getCallbackClient());
+    SetValuesClient client(getPool(), getCallbackClient());
 
     client.sendResultsSeparately(results);
 
@@ -193,7 +201,9 @@
                                                    .status = StatusCode::OK,
                                            }};
 
-    SetValuesClient client(getCallbackClient());
+    SetValuesClient client(getPool(), getCallbackClient());
+
+    client.addRequests({0, 1});
 
     (*(client.getResultCallback()))(results);
 
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index 8934a7b..d763f03 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "ConnectedClient.h"
 #include "DefaultVehicleHal.h"
 #include "MockVehicleCallback.h"
 
@@ -27,6 +28,7 @@
 #include <gtest/gtest.h>
 #include <utils/Log.h>
 
+#include <chrono>
 #include <list>
 #include <memory>
 #include <mutex>
@@ -67,6 +69,7 @@
 using ::ndk::ScopedFileDescriptor;
 
 using ::testing::Eq;
+using ::testing::UnorderedElementsAreArray;
 using ::testing::WhenSortedBy;
 
 constexpr int32_t INVALID_PROP_ID = 0;
@@ -356,6 +359,11 @@
         mCallbackClient = IVehicleCallback::fromBinder(mCallback->asBinder());
     }
 
+    void TearDown() override {
+        ASSERT_EQ(countPendingRequests(), static_cast<size_t>(0))
+                << "must have no pending requests when test finishes";
+    }
+
     MockVehicleHardware* getHardware() { return mHardwarePtr; }
 
     std::shared_ptr<IVehicle> getClient() { return mVhal; }
@@ -364,6 +372,12 @@
 
     MockVehicleCallback* getCallback() { return mCallback.get(); }
 
+    void setTimeout(int64_t timeoutInNano) { mVhal->setTimeout(timeoutInNano); }
+
+    size_t countPendingRequests() { return mVhal->mPendingRequestPool->countPendingRequests(); }
+
+    std::shared_ptr<PendingRequestPool> getPool() { return mVhal->mPendingRequestPool; }
+
     static Result<void> getValuesTestCases(size_t size, GetValueRequests& requests,
                                            std::vector<GetValueResult>& expectedResults,
                                            std::vector<GetValueRequest>& expectedHardwareRequests) {
@@ -389,15 +403,14 @@
             });
         }
 
-        auto result = LargeParcelableBase::parcelableVectorToStableLargeParcelable(
-                expectedHardwareRequests);
+        requests.payloads = expectedHardwareRequests;
+        auto result = LargeParcelableBase::parcelableToStableLargeParcelable(requests);
         if (!result.ok()) {
             return result.error();
         }
-        if (result.value() == nullptr) {
-            requests.payloads = expectedHardwareRequests;
-        } else {
+        if (result.value() != nullptr) {
             requests.sharedMemoryFd = std::move(*result.value());
+            requests.payloads.clear();
         }
         return {};
     }
@@ -423,14 +436,13 @@
             });
         }
 
-        auto result = LargeParcelableBase::parcelableVectorToStableLargeParcelable(
-                expectedHardwareRequests);
+        requests.payloads = expectedHardwareRequests;
+        auto result = LargeParcelableBase::parcelableToStableLargeParcelable(requests);
         if (!result.ok()) {
             return result.error();
         }
-        if (result.value() == nullptr) {
-            requests.payloads = expectedHardwareRequests;
-        } else {
+        if (result.value() != nullptr) {
+            requests.payloads.clear();
             requests.sharedMemoryFd = std::move(*result.value());
         }
         return {};
@@ -490,13 +502,10 @@
 
     ASSERT_TRUE(status.isOk()) << "getAllPropConfigs failed: " << status.getMessage();
     ASSERT_TRUE(output.payloads.empty());
-    Result<std::optional<std::vector<VehiclePropConfig>>> result =
-            LargeParcelableBase::stableLargeParcelableToParcelableVector<VehiclePropConfig>(
-                    output.sharedMemoryFd);
+    auto result = LargeParcelableBase::stableLargeParcelableToParcelable(output);
     ASSERT_TRUE(result.ok()) << "failed to parse result shared memory file: "
                              << result.error().message();
-    ASSERT_TRUE(result.value().has_value()) << "empty parsed value";
-    ASSERT_EQ(result.value().value(), testConfigs);
+    ASSERT_EQ(result.value().getObject()->payloads, testConfigs);
 }
 
 TEST_F(DefaultVehicleHalTest, testGetValuesSmall) {
@@ -544,11 +553,9 @@
     ASSERT_TRUE(getValueResults.payloads.empty())
             << "payload should be empty, shared memory file should be used";
 
-    auto result = LargeParcelableBase::stableLargeParcelableToParcelableVector<GetValueResult>(
-            getValueResults.sharedMemoryFd);
+    auto result = LargeParcelableBase::stableLargeParcelableToParcelable(getValueResults);
     ASSERT_TRUE(result.ok()) << "failed to parse shared memory file";
-    ASSERT_TRUE(result.value().has_value()) << "no parsed value";
-    ASSERT_EQ(result.value().value(), expectedResults) << "results mismatch";
+    ASSERT_EQ(result.value().getObject()->payloads, expectedResults) << "results mismatch";
     EXPECT_EQ(countClients(), static_cast<size_t>(1));
 }
 
@@ -577,6 +584,145 @@
     ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG));
 }
 
+TEST_F(DefaultVehicleHalTest, testGetValuesFinishBeforeTimeout) {
+    // timeout: 0.1s
+    int64_t timeout = 100000000;
+    setTimeout(timeout);
+
+    GetValueRequests requests;
+    std::vector<GetValueResult> expectedResults;
+    std::vector<GetValueRequest> expectedHardwareRequests;
+
+    ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+    // The response would be returned after 0.05s.
+    getHardware()->setSleepTime(timeout / 2);
+    getHardware()->addGetValueResponses(expectedResults);
+
+    auto status = getClient()->getValues(getCallbackClient(), requests);
+
+    ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
+
+    // Wait for the response.
+    std::this_thread::sleep_for(std::chrono::nanoseconds(timeout));
+
+    auto maybeGetValueResults = getCallback()->nextGetValueResults();
+    ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
+    EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch";
+    ASSERT_FALSE(getCallback()->nextGetValueResults().has_value()) << "more results than expected";
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesFinishAfterTimeout) {
+    // timeout: 0.1s
+    int64_t timeout = 100000000;
+    setTimeout(timeout);
+
+    GetValueRequests requests;
+    std::vector<GetValueResult> expectedResults;
+    std::vector<GetValueRequest> expectedHardwareRequests;
+
+    ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+    // The response would be returned after 0.2s.
+    getHardware()->setSleepTime(timeout * 2);
+    getHardware()->addGetValueResponses(expectedResults);
+
+    auto status = getClient()->getValues(getCallbackClient(), requests);
+
+    ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
+
+    // Wait for the response.
+    std::this_thread::sleep_for(std::chrono::nanoseconds(timeout * 5));
+
+    for (size_t i = 0; i < expectedResults.size(); i++) {
+        expectedResults[i] = {
+                .requestId = expectedResults[i].requestId,
+                .status = StatusCode::TRY_AGAIN,
+                .prop = std::nullopt,
+        };
+    }
+
+    auto maybeGetValueResults = getCallback()->nextGetValueResults();
+    ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
+    ASSERT_THAT(maybeGetValueResults.value().payloads, UnorderedElementsAreArray(expectedResults))
+            << "results mismatch, expect TRY_AGAIN error.";
+    ASSERT_FALSE(getCallback()->nextGetValueResults().has_value()) << "more results than expected";
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesDuplicateRequestIdsInTwoRequests) {
+    // timeout: 0.1s
+    int64_t timeout = 100000000;
+    setTimeout(timeout);
+
+    GetValueRequests requests;
+    std::vector<GetValueResult> expectedResults;
+    std::vector<GetValueRequest> expectedHardwareRequests;
+
+    ASSERT_TRUE(getValuesTestCases(1, requests, expectedResults, expectedHardwareRequests).ok());
+
+    getHardware()->setSleepTime(timeout * 2);
+    getHardware()->addGetValueResponses(expectedResults);
+
+    auto status = getClient()->getValues(getCallbackClient(), requests);
+
+    ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
+
+    // Use the same request ID again.
+    status = getClient()->getValues(getCallbackClient(), requests);
+
+    ASSERT_FALSE(status.isOk())
+            << "Use the same request ID before the previous request finishes must fail";
+
+    // Wait for the request to finish.
+    std::this_thread::sleep_for(std::chrono::nanoseconds(timeout * 5));
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesDuplicateRequestIdsInOneRequest) {
+    GetValueRequests requests = {.payloads = {
+                                         {
+                                                 .requestId = 0,
+                                                 .prop =
+                                                         VehiclePropValue{
+                                                                 .prop = testInt32VecProp(0),
+                                                         },
+                                         },
+                                         {
+                                                 .requestId = 0,
+                                                 .prop =
+                                                         VehiclePropValue{
+                                                                 .prop = testInt32VecProp(1),
+                                                         },
+                                         },
+                                 }};
+
+    auto status = getClient()->getValues(getCallbackClient(), requests);
+
+    ASSERT_FALSE(status.isOk()) << "duplicate Ids in one request must fail";
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesDuplicateRequestProps) {
+    GetValueRequests requests = {.payloads = {
+                                         {
+                                                 .requestId = 0,
+                                                 .prop =
+                                                         VehiclePropValue{
+                                                                 .prop = testInt32VecProp(0),
+                                                         },
+                                         },
+                                         {
+                                                 .requestId = 1,
+                                                 .prop =
+                                                         VehiclePropValue{
+                                                                 .prop = testInt32VecProp(0),
+                                                         },
+                                         },
+                                 }};
+
+    auto status = getClient()->getValues(getCallbackClient(), requests);
+
+    ASSERT_FALSE(status.isOk()) << "duplicate request properties in one request must fail";
+}
+
 TEST_F(DefaultVehicleHalTest, testSetValuesSmall) {
     SetValueRequests requests;
     std::vector<SetValueResult> expectedResults;
@@ -621,11 +767,9 @@
     ASSERT_TRUE(setValueResults.payloads.empty())
             << "payload should be empty, shared memory file should be used";
 
-    auto result = LargeParcelableBase::stableLargeParcelableToParcelableVector<SetValueResult>(
-            setValueResults.sharedMemoryFd);
+    auto result = LargeParcelableBase::stableLargeParcelableToParcelable(setValueResults);
     ASSERT_TRUE(result.ok()) << "failed to parse shared memory file";
-    ASSERT_TRUE(result.value().has_value()) << "no parsed value";
-    ASSERT_EQ(result.value().value(), expectedResults) << "results mismatch";
+    ASSERT_EQ(result.value().getObject()->payloads, expectedResults) << "results mismatch";
     EXPECT_EQ(countClients(), static_cast<size_t>(1));
 }
 
@@ -684,6 +828,148 @@
             << "results from hardware mismatch";
 }
 
+TEST_F(DefaultVehicleHalTest, testSetValuesFinishBeforeTimeout) {
+    // timeout: 0.1s
+    int64_t timeout = 100000000;
+    setTimeout(timeout);
+
+    SetValueRequests requests;
+    std::vector<SetValueResult> expectedResults;
+    std::vector<SetValueRequest> expectedHardwareRequests;
+
+    ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+    // The response would be returned after 0.05s.
+    getHardware()->setSleepTime(timeout / 2);
+    getHardware()->addSetValueResponses(expectedResults);
+
+    auto status = getClient()->setValues(getCallbackClient(), requests);
+
+    ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
+
+    // Wait for the response.
+    std::this_thread::sleep_for(std::chrono::nanoseconds(timeout));
+
+    auto maybeSetValueResults = getCallback()->nextSetValueResults();
+    ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
+    EXPECT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch";
+    ASSERT_FALSE(getCallback()->nextSetValueResults().has_value()) << "more results than expected";
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesFinishAfterTimeout) {
+    // timeout: 0.1s
+    int64_t timeout = 100000000;
+    setTimeout(timeout);
+
+    SetValueRequests requests;
+    std::vector<SetValueResult> expectedResults;
+    std::vector<SetValueRequest> expectedHardwareRequests;
+
+    ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+    // The response would be returned after 0.2s.
+    getHardware()->setSleepTime(timeout * 2);
+    getHardware()->addSetValueResponses(expectedResults);
+
+    auto status = getClient()->setValues(getCallbackClient(), requests);
+
+    ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
+
+    // Wait for the response.
+    std::this_thread::sleep_for(std::chrono::nanoseconds(timeout * 5));
+
+    for (size_t i = 0; i < expectedResults.size(); i++) {
+        expectedResults[i] = {
+                .requestId = expectedResults[i].requestId,
+                .status = StatusCode::TRY_AGAIN,
+        };
+    }
+
+    auto maybeSetValueResults = getCallback()->nextSetValueResults();
+    ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
+    ASSERT_THAT(maybeSetValueResults.value().payloads, UnorderedElementsAreArray(expectedResults))
+            << "results mismatch, expect TRY_AGAIN error.";
+    ASSERT_FALSE(getCallback()->nextSetValueResults().has_value()) << "more results than expected";
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesDuplicateRequestIdsInTwoRequests) {
+    // timeout: 0.1s
+    int64_t timeout = 100000000;
+    setTimeout(timeout);
+
+    SetValueRequests requests;
+    std::vector<SetValueResult> expectedResults;
+    std::vector<SetValueRequest> expectedHardwareRequests;
+
+    ASSERT_TRUE(setValuesTestCases(1, requests, expectedResults, expectedHardwareRequests).ok());
+
+    getHardware()->setSleepTime(timeout * 2);
+    getHardware()->addSetValueResponses(expectedResults);
+
+    auto status = getClient()->setValues(getCallbackClient(), requests);
+
+    ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
+
+    // Use the same request ID again.
+    status = getClient()->setValues(getCallbackClient(), requests);
+
+    ASSERT_FALSE(status.isOk())
+            << "Use the same request ID before the previous request finishes must fail";
+
+    // Wait for the request to finish.
+    std::this_thread::sleep_for(std::chrono::nanoseconds(timeout * 5));
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesDuplicateRequestIdsInOneRequest) {
+    SetValueRequests requests = {.payloads = {
+                                         {
+                                                 .requestId = 0,
+                                                 .value =
+                                                         VehiclePropValue{
+                                                                 .prop = testInt32VecProp(0),
+                                                                 .value.int32Values = {0},
+                                                         },
+                                         },
+                                         {
+                                                 .requestId = 0,
+                                                 .value =
+                                                         VehiclePropValue{
+                                                                 .prop = testInt32VecProp(1),
+                                                                 .value.int32Values = {0},
+                                                         },
+                                         },
+                                 }};
+
+    auto status = getClient()->setValues(getCallbackClient(), requests);
+
+    ASSERT_FALSE(status.isOk()) << "duplicate Ids in one request must fail";
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesDuplicateRequestProps) {
+    SetValueRequests requests = {.payloads = {
+                                         {
+                                                 .requestId = 0,
+                                                 .value =
+                                                         VehiclePropValue{
+                                                                 .prop = testInt32VecProp(0),
+                                                                 .value.int32Values = {0},
+                                                         },
+                                         },
+                                         {
+                                                 .requestId = 1,
+                                                 .value =
+                                                         VehiclePropValue{
+                                                                 .prop = testInt32VecProp(0),
+                                                                 .value.int32Values = {0},
+                                                         },
+                                         },
+                                 }};
+
+    auto status = getClient()->setValues(getCallbackClient(), requests);
+
+    ASSERT_FALSE(status.isOk()) << "duplicate request properties in one request must fail";
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/PendingRequestPoolTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/PendingRequestPoolTest.cpp
new file mode 100644
index 0000000..9c9e4b9
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/test/PendingRequestPoolTest.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 "PendingRequestPool.h"
+
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <unordered_set>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+
+using ::testing::ElementsAre;
+using ::testing::UnorderedElementsAre;
+using ::testing::WhenSorted;
+
+class PendingRequestPoolTest : public ::testing::Test {
+  public:
+    void SetUp() override { mPool = std::make_unique<PendingRequestPool>(TEST_TIMEOUT); }
+
+    void TearDown() override {
+        if (mPool != nullptr) {
+            ASSERT_EQ(mPool->countPendingRequests(getTestClientId()), static_cast<size_t>(0))
+                    << "at least one pending request still exists in the pool when finish";
+        }
+    }
+
+    PendingRequestPool* getPool() { return mPool.get(); }
+
+    void destroyPool() { mPool.reset(); }
+
+    int64_t getTimeout() { return TEST_TIMEOUT; }
+
+    const void* getTestClientId() { return reinterpret_cast<const void*>(0); }
+
+  private:
+    // Test timeout is 0.1s.
+    static const int64_t TEST_TIMEOUT = 100000000;
+
+    std::unique_ptr<PendingRequestPool> mPool;
+};
+
+TEST_F(PendingRequestPoolTest, testFinishAllRequests) {
+    std::mutex lock;
+    std::vector<int64_t> timeoutRequestIds;
+
+    std::unordered_set<int64_t> requestIds;
+    for (int64_t i = 0; i < 10; i++) {
+        requestIds.insert(i);
+    }
+
+    auto callback = std::make_shared<PendingRequestPool::TimeoutCallbackFunc>(
+            [&lock, &timeoutRequestIds](const std::unordered_set<int64_t>& requests) {
+                std::scoped_lock<std::mutex> lockGuard(lock);
+                for (int64_t request : requests) {
+                    timeoutRequestIds.push_back(request);
+                }
+            });
+
+    ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), requestIds, callback));
+
+    for (int64_t i = 0; i < 10; i++) {
+        ASSERT_TRUE(getPool()->isRequestPending(getTestClientId(), i));
+    }
+
+    for (int64_t i = 0; i < 10; i++) {
+        ASSERT_THAT(getPool()->tryFinishRequests(getTestClientId(), {i}), UnorderedElementsAre(i));
+    }
+
+    for (int64_t i = 0; i < 10; i++) {
+        ASSERT_FALSE(getPool()->isRequestPending(getTestClientId(), i));
+    }
+}
+
+TEST_F(PendingRequestPoolTest, testFinishHalfOfRequest) {
+    int64_t timeout = getTimeout();
+    std::mutex lock;
+    std::vector<int64_t> timeoutRequestIds;
+
+    std::unordered_set<int64_t> requestIds;
+    for (int64_t i = 0; i < 10; i++) {
+        requestIds.insert(i);
+    }
+
+    auto callback = std::make_shared<PendingRequestPool::TimeoutCallbackFunc>(
+            [&lock, &timeoutRequestIds](const std::unordered_set<int64_t>& requests) {
+                std::scoped_lock<std::mutex> lockGuard(lock);
+                for (int64_t request : requests) {
+                    timeoutRequestIds.push_back(request);
+                }
+            });
+
+    ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), requestIds, callback));
+
+    for (int64_t i = 0; i < 10; i++) {
+        ASSERT_TRUE(getPool()->isRequestPending(getTestClientId(), i));
+    }
+
+    // Finish half of the requests.
+    requestIds.clear();
+    for (int64_t i = 0; i < 5; i++) {
+        requestIds.insert(i);
+    }
+
+    ASSERT_EQ(getPool()->tryFinishRequests(getTestClientId(), requestIds), requestIds);
+
+    for (int64_t i = 0; i < 5; i++) {
+        ASSERT_FALSE(getPool()->isRequestPending(getTestClientId(), i));
+    }
+    for (int64_t i = 5; i < 10; i++) {
+        ASSERT_TRUE(getPool()->isRequestPending(getTestClientId(), i));
+    }
+
+    // Wait until the unfinished requests timeout. The check interval is timeout, so at max we
+    // would wait an additional interval, which is 2 * timeout until the callback is called.
+    std::this_thread::sleep_for(2 * std::chrono::nanoseconds(timeout));
+
+    ASSERT_THAT(timeoutRequestIds, WhenSorted(ElementsAre(5, 6, 7, 8, 9)));
+}
+
+TEST_F(PendingRequestPoolTest, testFinishRequestTwice) {
+    std::mutex lock;
+    std::vector<int64_t> timeoutRequestIds;
+
+    auto callback = std::make_shared<PendingRequestPool::TimeoutCallbackFunc>(
+            [&lock, &timeoutRequestIds](const std::unordered_set<int64_t>& requests) {
+                std::scoped_lock<std::mutex> lockGuard(lock);
+                for (int64_t request : requests) {
+                    timeoutRequestIds.push_back(request);
+                }
+            });
+
+    ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), {0}, callback));
+
+    ASSERT_THAT(getPool()->tryFinishRequests(getTestClientId(), {0}), UnorderedElementsAre(0))
+            << "failed to finish an added request";
+    ASSERT_TRUE(getPool()->tryFinishRequests(getTestClientId(), {0}).empty())
+            << "finish a request second time must return empty result";
+}
+
+TEST_F(PendingRequestPoolTest, testFinishRequestNonExistingId) {
+    std::mutex lock;
+    std::vector<int64_t> timeoutRequestIds;
+
+    auto callback = std::make_shared<PendingRequestPool::TimeoutCallbackFunc>(
+            [&lock, &timeoutRequestIds](const std::unordered_set<int64_t>& requests) {
+                std::scoped_lock<std::mutex> lockGuard(lock);
+                for (int64_t request : requests) {
+                    timeoutRequestIds.push_back(request);
+                }
+            });
+
+    ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), {0, 1, 2}, callback));
+
+    ASSERT_THAT(getPool()->tryFinishRequests(getTestClientId(), {0, 1, 2, 3}),
+                UnorderedElementsAre(0, 1, 2))
+            << "finished request IDs must not contain non-existing request ID";
+    // Even though one of the request to finish does not exist, the rest of the requests should be
+    // finished.
+    ASSERT_EQ(getPool()->countPendingRequests(getTestClientId()), static_cast<size_t>(0))
+            << "requests not being finished correctly";
+}
+
+TEST_F(PendingRequestPoolTest, testFinishAfterTimeout) {
+    std::mutex lock;
+    std::vector<int64_t> timeoutRequestIds;
+
+    auto callback = std::make_shared<PendingRequestPool::TimeoutCallbackFunc>(
+            [&lock, &timeoutRequestIds](const std::unordered_set<int64_t>& requests) {
+                std::scoped_lock<std::mutex> lockGuard(lock);
+                for (int64_t request : requests) {
+                    timeoutRequestIds.push_back(request);
+                }
+            });
+
+    ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), {0}, callback));
+
+    std::this_thread::sleep_for(2 * std::chrono::nanoseconds(getTimeout()));
+
+    ASSERT_TRUE(getPool()->tryFinishRequests(getTestClientId(), {0}).empty())
+            << "finish a request after timeout must do nothing";
+}
+
+TEST_F(PendingRequestPoolTest, testDestroyWithPendingRequests) {
+    std::mutex lock;
+    std::vector<int64_t> timeoutRequestIds;
+
+    auto callback = std::make_shared<PendingRequestPool::TimeoutCallbackFunc>(
+            [&lock, &timeoutRequestIds](const std::unordered_set<int64_t>& requests) {
+                std::scoped_lock<std::mutex> lockGuard(lock);
+                for (int64_t request : requests) {
+                    timeoutRequestIds.push_back(request);
+                }
+            });
+
+    ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), {0}, callback));
+
+    destroyPool();
+
+    // Before the pool is destroyed, the pending requests should be notified as timeout.
+    ASSERT_THAT(timeoutRequestIds, UnorderedElementsAre(0))
+            << "timeout not triggered when the pool is destroyed";
+}
+
+TEST_F(PendingRequestPoolTest, testDuplicateRequestId) {
+    auto callback = std::make_shared<PendingRequestPool::TimeoutCallbackFunc>(
+            [](std::unordered_set<int64_t>) {});
+
+    ASSERT_RESULT_OK(getPool()->addRequests(getTestClientId(), {0}, callback));
+    ASSERT_FALSE(getPool()->addRequests(getTestClientId(), {1, 2, 0}, callback).ok())
+            << "adding duplicate request IDs must fail";
+
+    ASSERT_THAT(getPool()->tryFinishRequests(getTestClientId(), {0}), UnorderedElementsAre(0));
+}
+
+TEST_F(PendingRequestPoolTest, testSameRequestIdForDifferentClient) {
+    auto callback = std::make_shared<PendingRequestPool::TimeoutCallbackFunc>(
+            [](std::unordered_set<int64_t>) {});
+
+    ASSERT_RESULT_OK(getPool()->addRequests(reinterpret_cast<const void*>(0), {0}, callback));
+    ASSERT_RESULT_OK(getPool()->addRequests(reinterpret_cast<const void*>(1), {1, 2, 0}, callback));
+
+    ASSERT_THAT(getPool()->tryFinishRequests(reinterpret_cast<const void*>(0), {0}),
+                UnorderedElementsAre(0));
+    ASSERT_THAT(getPool()->tryFinishRequests(reinterpret_cast<const void*>(1), {1, 2, 0}),
+                UnorderedElementsAre(0, 1, 2));
+}
+
+TEST_F(PendingRequestPoolTest, testPendingRequestCountLimit) {
+    auto callback = std::make_shared<PendingRequestPool::TimeoutCallbackFunc>(
+            [](std::unordered_set<int64_t>) {});
+
+    std::unordered_set<int64_t> requests;
+
+    // MAX_PENDING_REQUEST_PER_CLIENT = 10000
+    for (size_t i = 0; i < 10000; i++) {
+        requests.insert(static_cast<int64_t>(i));
+    }
+    ASSERT_RESULT_OK(getPool()->addRequests(reinterpret_cast<const void*>(0), requests, callback));
+
+    auto result = getPool()->addRequests(reinterpret_cast<const void*>(0),
+                                         {static_cast<int64_t>(10000)}, callback);
+    ASSERT_FALSE(result.ok()) << "adding more pending requests than limit must fail";
+    ASSERT_EQ(result.error().code(), toInt(StatusCode::TRY_AGAIN));
+
+    getPool()->tryFinishRequests(reinterpret_cast<const void*>(0), requests);
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/vhal/test/RecurrentTimerTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/RecurrentTimerTest.cpp
new file mode 100644
index 0000000..d343cea
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/test/RecurrentTimerTest.cpp
@@ -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.
+ */
+
+#include "RecurrentTimer.h"
+
+#include <android-base/thread_annotations.h>
+#include <gtest/gtest.h>
+
+#include <chrono>
+#include <memory>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+class RecurrentTimerTest : public ::testing::Test {
+  public:
+    std::shared_ptr<RecurrentTimer::Callback> getCallback(size_t token) {
+        return std::make_shared<RecurrentTimer::Callback>([this, token] {
+            std::scoped_lock<std::mutex> lockGuard(mLock);
+
+            mCallbacks.push_back(token);
+        });
+    }
+
+    std::vector<size_t> getCalledCallbacks() {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+        return mCallbacks;
+    }
+
+    void clearCalledCallbacks() {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+        mCallbacks.clear();
+    }
+
+    size_t countTimerCallbackQueue(RecurrentTimer* timer) {
+        std::scoped_lock<std::mutex> lockGuard(timer->mLock);
+        return timer->mCallbackQueue.size();
+    }
+
+  private:
+    std::mutex mLock;
+    std::vector<size_t> mCallbacks GUARDED_BY(mLock);
+};
+
+TEST_F(RecurrentTimerTest, testRegisterCallback) {
+    RecurrentTimer timer;
+    // 0.1s
+    int64_t interval = 100000000;
+
+    auto action = getCallback(0);
+    timer.registerTimerCallback(interval, action);
+
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+
+    timer.unregisterTimerCallback(action);
+
+    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+    ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
+}
+
+TEST_F(RecurrentTimerTest, testRegisterUnregisterRegister) {
+    RecurrentTimer timer;
+    // 0.1s
+    int64_t interval = 100000000;
+
+    auto action = getCallback(0);
+    timer.registerTimerCallback(interval, action);
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+    timer.unregisterTimerCallback(action);
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+    clearCalledCallbacks();
+
+    timer.registerTimerCallback(interval, action);
+
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+
+    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+    ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
+}
+
+TEST_F(RecurrentTimerTest, testDestroyTimerWithCallback) {
+    std::unique_ptr<RecurrentTimer> timer = std::make_unique<RecurrentTimer>();
+    // 0.1s
+    int64_t interval = 100000000;
+
+    auto action = getCallback(0);
+    timer->registerTimerCallback(interval, action);
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+    timer.reset();
+
+    clearCalledCallbacks();
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+    ASSERT_TRUE(getCalledCallbacks().empty());
+}
+
+TEST_F(RecurrentTimerTest, testRegisterMultipleCallbacks) {
+    RecurrentTimer timer;
+    // 0.1s
+    int64_t interval1 = 100000000;
+    auto action1 = getCallback(1);
+    timer.registerTimerCallback(interval1, action1);
+    // 0.05s
+    int64_t interval2 = 50000000;
+    auto action2 = getCallback(2);
+    timer.registerTimerCallback(interval2, action2);
+    // 0.03s
+    int64_t interval3 = 30000000;
+    auto action3 = getCallback(3);
+    timer.registerTimerCallback(interval3, action3);
+
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+
+    timer.unregisterTimerCallback(action1);
+    timer.unregisterTimerCallback(action2);
+    timer.unregisterTimerCallback(action3);
+
+    size_t action1Count = 0;
+    size_t action2Count = 0;
+    size_t action3Count = 0;
+    for (size_t token : getCalledCallbacks()) {
+        if (token == 1) {
+            action1Count++;
+        }
+        if (token == 2) {
+            action2Count++;
+        }
+        if (token == 3) {
+            action3Count++;
+        }
+    }
+    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+    ASSERT_GE(action1Count, static_cast<size_t>(9));
+    // Theoretically trigger 20 times, but check for at least 15 times to be stable.
+    ASSERT_GE(action2Count, static_cast<size_t>(15));
+    // Theoretically trigger 33 times, but check for at least 25 times to be stable.
+    ASSERT_GE(action3Count, static_cast<size_t>(25));
+}
+
+TEST_F(RecurrentTimerTest, testRegisterSameCallbackMultipleTimes) {
+    RecurrentTimer timer;
+    // 0.02s
+    int64_t interval1 = 20000000;
+    // 0.01s
+    int64_t interval2 = 10000000;
+
+    auto action = getCallback(0);
+    for (int i = 0; i < 10; i++) {
+        timer.registerTimerCallback(interval1, action);
+        timer.registerTimerCallback(interval2, action);
+    }
+
+    clearCalledCallbacks();
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+    ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
+
+    timer.unregisterTimerCallback(action);
+
+    // Make sure there is no item in the callback queue.
+    ASSERT_EQ(countTimerCallbackQueue(&timer), static_cast<size_t>(0));
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
new file mode 100644
index 0000000..fa08d6c
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SubscriptionManager.h"
+
+#include <VehicleHalTypes.h>
+
+#include <aidl/android/hardware/automotive/vehicle/BnVehicleCallback.h>
+#include <android-base/thread_annotations.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <float.h>
+#include <chrono>
+#include <list>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::BnVehicleCallback;
+using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
+using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
+using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
+using ::ndk::ScopedAStatus;
+using ::testing::ElementsAre;
+using ::testing::WhenSorted;
+
+class PropertyCallback final : public BnVehicleCallback {
+  public:
+    ScopedAStatus onGetValues(const GetValueResults&) override { return ScopedAStatus::ok(); }
+
+    ScopedAStatus onSetValues(const SetValueResults&) override { return ScopedAStatus::ok(); }
+
+    ScopedAStatus onPropertyEvent(const VehiclePropValues& values, int32_t) override {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+        for (const auto& value : values.payloads) {
+            mEvents.push_back(value);
+        }
+        return ScopedAStatus::ok();
+    }
+
+    ScopedAStatus onPropertySetError(const VehiclePropErrors&) override {
+        return ScopedAStatus::ok();
+    }
+
+    // Test functions.
+    std::list<VehiclePropValue> getEvents() {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+        return mEvents;
+    }
+
+    void clearEvents() {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+        mEvents.clear();
+    }
+
+  private:
+    std::mutex mLock;
+    std::list<VehiclePropValue> mEvents GUARDED_BY(mLock);
+};
+
+class SubscriptionManagerTest : public ::testing::Test {
+  public:
+    void SetUp() override {
+        mManager = std::make_unique<SubscriptionManager>(
+                [](const std::shared_ptr<IVehicleCallback>& callback,
+                   const VehiclePropValue& value) {
+                    callback->onPropertyEvent(
+                            VehiclePropValues{
+                                    .payloads = {value},
+                            },
+                            0);
+                });
+        mCallback = ::ndk::SharedRefBase::make<PropertyCallback>();
+        mCallbackClient = IVehicleCallback::fromBinder(mCallback->asBinder());
+    }
+
+    SubscriptionManager* getManager() { return mManager.get(); }
+
+    std::shared_ptr<IVehicleCallback> getCallbackClient() { return mCallbackClient; }
+
+    PropertyCallback* getCallback() { return mCallback.get(); }
+
+    std::list<VehiclePropValue> getEvents() { return getCallback()->getEvents(); }
+
+    void clearEvents() { return getCallback()->clearEvents(); }
+
+  private:
+    std::unique_ptr<SubscriptionManager> mManager;
+    std::shared_ptr<PropertyCallback> mCallback;
+    std::shared_ptr<IVehicleCallback> mCallbackClient;
+};
+
+TEST_F(SubscriptionManagerTest, testSubscribeGlobalContinuous) {
+    std::vector<SubscribeOptions> options = {{
+            .propId = 0,
+            .areaIds = {0},
+            .sampleRate = 10.0,
+    }};
+
+    auto result = getManager()->subscribe(getCallbackClient(), options, true);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+
+    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+    ASSERT_GE(getEvents().size(), static_cast<size_t>(9));
+    EXPECT_EQ(getEvents().back().prop, 0);
+    EXPECT_EQ(getEvents().back().areaId, 0);
+}
+
+TEST_F(SubscriptionManagerTest, testSubscribeMultiplePropsGlobalContinuous) {
+    std::vector<SubscribeOptions> options = {{
+                                                     .propId = 0,
+                                                     .areaIds = {0},
+                                                     .sampleRate = 10.0,
+                                             },
+                                             {
+                                                     .propId = 1,
+                                                     .areaIds = {0},
+                                                     .sampleRate = 20.0,
+                                             }};
+
+    auto result = getManager()->subscribe(getCallbackClient(), options, true);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+
+    size_t event0Count = 0;
+    size_t event1Count = 0;
+
+    for (const auto& event : getEvents()) {
+        if (event.prop == 0) {
+            event0Count++;
+        } else {
+            event1Count++;
+        }
+    }
+
+    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+    EXPECT_GE(event0Count, static_cast<size_t>(9));
+    // Theoretically trigger 20 times, but check for at least 15 times to be stable.
+    EXPECT_GE(event1Count, static_cast<size_t>(15));
+}
+
+TEST_F(SubscriptionManagerTest, testOverrideSubscriptionContinuous) {
+    std::vector<SubscribeOptions> options = {{
+            .propId = 0,
+            .areaIds = {0},
+            .sampleRate = 20.0,
+    }};
+
+    auto result = getManager()->subscribe(getCallbackClient(), options, true);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+
+    // Override sample rate to be 10.0.
+    options[0].sampleRate = 10.0;
+    result = getManager()->subscribe(getCallbackClient(), options, true);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+
+    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+    EXPECT_GE(getEvents().size(), static_cast<size_t>(9));
+    EXPECT_LE(getEvents().size(), static_cast<size_t>(11));
+}
+
+TEST_F(SubscriptionManagerTest, testSubscribeMultipleAreasContinuous) {
+    std::vector<SubscribeOptions> options = {
+            {
+                    .propId = 0,
+                    .areaIds = {0, 1},
+                    .sampleRate = 10.0,
+            },
+    };
+
+    auto result = getManager()->subscribe(getCallbackClient(), options, true);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+
+    size_t area0Count = 0;
+    size_t area1Count = 0;
+
+    for (const auto& event : getEvents()) {
+        if (event.areaId == 0) {
+            area0Count++;
+        } else {
+            area1Count++;
+        }
+    }
+
+    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+    EXPECT_GE(area0Count, static_cast<size_t>(9));
+    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+    EXPECT_GE(area1Count, static_cast<size_t>(9));
+}
+
+TEST_F(SubscriptionManagerTest, testUnsubscribeGlobalContinuous) {
+    std::vector<SubscribeOptions> options = {{
+            .propId = 0,
+            .areaIds = {0},
+            .sampleRate = 10.0,
+    }};
+
+    auto result = getManager()->subscribe(getCallbackClient(), options, true);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+
+    result = getManager()->unsubscribe(getCallbackClient());
+    ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
+
+    clearEvents();
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+    ASSERT_TRUE(getEvents().empty());
+}
+
+TEST_F(SubscriptionManagerTest, testUnsubscribeMultipleAreas) {
+    std::vector<SubscribeOptions> options = {
+            {
+                    .propId = 0,
+                    .areaIds = {0, 1, 2, 3, 4},
+                    .sampleRate = 10.0,
+            },
+            {
+                    .propId = 1,
+                    .areaIds = {0},
+                    .sampleRate = 10.0,
+            },
+    };
+
+    auto result = getManager()->subscribe(getCallbackClient(), options, true);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+
+    result = getManager()->unsubscribe(getCallbackClient(), std::vector<int32_t>({0}));
+    ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
+
+    clearEvents();
+
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+
+    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+    EXPECT_GE(getEvents().size(), static_cast<size_t>(9));
+
+    for (const auto& event : getEvents()) {
+        EXPECT_EQ(event.prop, 1);
+    }
+}
+
+TEST_F(SubscriptionManagerTest, testUnsubscribeByCallback) {
+    std::vector<SubscribeOptions> options = {
+            {
+                    .propId = 0,
+                    .areaIds = {0, 1, 2, 3, 4},
+                    .sampleRate = 10.0,
+            },
+            {
+                    .propId = 1,
+                    .areaIds = {0},
+                    .sampleRate = 10.0,
+            },
+    };
+
+    auto result = getManager()->subscribe(getCallbackClient(), options, true);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+
+    result = getManager()->unsubscribe(getCallbackClient());
+    ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
+
+    clearEvents();
+
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+
+    EXPECT_TRUE(getEvents().empty());
+}
+
+TEST_F(SubscriptionManagerTest, testUnsubscribeFailure) {
+    std::vector<SubscribeOptions> options = {
+            {
+                    .propId = 0,
+                    .areaIds = {0, 1, 2, 3, 4},
+            },
+            {
+                    .propId = 1,
+                    .areaIds = {0},
+            },
+    };
+
+    auto result = getManager()->subscribe(getCallbackClient(), options, false);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+
+    // Property ID: 2 was not subscribed.
+    result = getManager()->unsubscribe(getCallbackClient(), std::vector<int32_t>({0, 1, 2}));
+    ASSERT_FALSE(result.ok()) << "unsubscribe an unsubscribed property must fail";
+
+    // Since property 0 and property 1 was not unsubscribed successfully, we should be able to
+    // unsubscribe them again.
+    result = getManager()->unsubscribe(getCallbackClient(), std::vector<int32_t>({0, 1}));
+    ASSERT_TRUE(result.ok()) << "a failed unsubscription must not unsubscribe any properties"
+                             << result.error().message();
+}
+
+TEST_F(SubscriptionManagerTest, testSubscribeOnchange) {
+    std::vector<SubscribeOptions> options1 = {
+            {
+                    .propId = 0,
+                    .areaIds = {0, 1},
+            },
+            {
+                    .propId = 1,
+                    .areaIds = {0},
+            },
+    };
+    std::vector<SubscribeOptions> options2 = {
+            {
+                    .propId = 0,
+                    .areaIds = {0},
+            },
+    };
+
+    std::shared_ptr<IVehicleCallback> client1 = IVehicleCallback::fromBinder(
+            ::ndk::SharedRefBase::make<PropertyCallback>()->asBinder());
+    std::shared_ptr<IVehicleCallback> client2 = IVehicleCallback::fromBinder(
+            ::ndk::SharedRefBase::make<PropertyCallback>()->asBinder());
+    auto result = getManager()->subscribe(client1, options1, false);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+    result = getManager()->subscribe(client2, options2, false);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+
+    std::vector<VehiclePropValue> updatedValues = {
+            {
+                    .prop = 0,
+                    .areaId = 0,
+            },
+            {
+                    .prop = 0,
+                    .areaId = 1,
+            },
+            {
+                    .prop = 1,
+                    .areaId = 0,
+            },
+            {
+                    .prop = 1,
+                    .areaId = 1,
+            },
+    };
+    auto clients = getManager()->getSubscribedClients(updatedValues);
+
+    ASSERT_THAT(clients[client1],
+                WhenSorted(ElementsAre(&updatedValues[0], &updatedValues[1], &updatedValues[2])));
+    ASSERT_THAT(clients[client2], ElementsAre(&updatedValues[0]));
+}
+
+TEST_F(SubscriptionManagerTest, testSubscribeInvalidOption) {
+    std::vector<SubscribeOptions> options = {
+            {
+                    .propId = 0,
+                    .areaIds = {0, 1, 2, 3, 4},
+                    // invalid sample rate.
+                    .sampleRate = 0.0,
+            },
+            {
+                    .propId = 1,
+                    .areaIds = {0},
+                    .sampleRate = 10.0,
+            },
+    };
+
+    auto result = getManager()->subscribe(getCallbackClient(), options, true);
+    ASSERT_FALSE(result.ok()) << "subscribe with invalid sample rate must fail";
+    ASSERT_TRUE(getManager()
+                        ->getSubscribedClients({{
+                                                        .prop = 0,
+                                                        .areaId = 0,
+                                                },
+                                                {
+                                                        .prop = 1,
+                                                        .areaId = 0,
+                                                }})
+                        .empty())
+            << "no property should be subscribed if error is returned";
+}
+
+TEST_F(SubscriptionManagerTest, testSubscribeNoAreaIds) {
+    std::vector<SubscribeOptions> options = {
+            {
+                    .propId = 0,
+                    .areaIds = {},
+                    .sampleRate = 1.0,
+            },
+            {
+                    .propId = 1,
+                    .areaIds = {0},
+                    .sampleRate = 10.0,
+            },
+    };
+
+    auto result = getManager()->subscribe(getCallbackClient(), options, true);
+    ASSERT_FALSE(result.ok()) << "subscribe with invalid sample rate must fail";
+    ASSERT_TRUE(getManager()
+                        ->getSubscribedClients({{
+                                .prop = 1,
+                                .areaId = 0,
+                        }})
+                        .empty())
+            << "no property should be subscribed if error is returned";
+}
+
+TEST_F(SubscriptionManagerTest, testUnsubscribeOnchange) {
+    std::vector<SubscribeOptions> options = {
+            {
+                    .propId = 0,
+                    .areaIds = {0, 1},
+            },
+            {
+                    .propId = 1,
+                    .areaIds = {0},
+            },
+    };
+
+    auto result = getManager()->subscribe(getCallbackClient(), options, false);
+    ASSERT_TRUE(result.ok()) << "failed to subscribe: " << result.error().message();
+
+    result = getManager()->unsubscribe(getCallbackClient(), std::vector<int32_t>({0}));
+    ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
+
+    std::vector<VehiclePropValue> updatedValues = {
+            {
+                    .prop = 0,
+                    .areaId = 0,
+            },
+            {
+                    .prop = 1,
+                    .areaId = 0,
+            },
+    };
+    auto clients = getManager()->getSubscribedClients(updatedValues);
+
+    ASSERT_THAT(clients[getCallbackClient()], ElementsAre(&updatedValues[1]));
+}
+
+TEST_F(SubscriptionManagerTest, testCheckSampleRateValid) {
+    ASSERT_TRUE(SubscriptionManager::checkSampleRate(1.0));
+}
+
+TEST_F(SubscriptionManagerTest, testCheckSampleRateInvalidTooSmall) {
+    ASSERT_FALSE(SubscriptionManager::checkSampleRate(FLT_MIN));
+}
+
+TEST_F(SubscriptionManagerTest, testCheckSampleRateInvalidZero) {
+    ASSERT_FALSE(SubscriptionManager::checkSampleRate(0));
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationContext.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationContext.aidl
index 295fde9..3a6461e 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationContext.aidl
@@ -31,12 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.biometrics.common;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable OperationContext {
+  int id = 0;
+  android.hardware.biometrics.common.OperationReason reason = android.hardware.biometrics.common.OperationReason.UNKNOWN;
+  boolean isAoD = false;
+  boolean isCrypto = false;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationReason.aidl
similarity index 88%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationReason.aidl
index 295fde9..3da3a6a 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationReason.aidl
@@ -31,12 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+package android.hardware.biometrics.common;
+@Backing(type="byte") @VintfStability
+enum OperationReason {
+  UNKNOWN = 0,
+  BIOMETRIC_PROMPT = 1,
+  KEYGUARD = 2,
 }
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/OperationContext.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/OperationContext.aidl
new file mode 100644
index 0000000..390e698
--- /dev/null
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/OperationContext.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.biometrics.common;
+
+import android.hardware.biometrics.common.OperationReason;
+
+/**
+ * Additional context associated with an operation.
+ */
+@VintfStability
+parcelable OperationContext {
+    /**
+     * An identifier for the logical action that the user is engaged in. These identifiers are
+     * not guaranteed to be unique. However, the framework will not reuse identifiers within
+     * short periods of time so they can be made unique, if needed, by appending a timestamp.
+     *
+     * Zero if the reason is OperationReason.UNKNOWN.
+     */
+    int id = 0;
+
+    /**
+     * A logical reason for this operation.
+     *
+     * This should be interpreted as a hint to enable optimizations or tracing. The
+     * framework may choose to use OperationReason.UNKNOWN at any time based on the device's
+     * policy.
+     */
+    OperationReason reason = OperationReason.UNKNOWN;
+
+    /* Flag indicating that the display is in AoD mode. */
+    boolean isAoD = false;
+
+    /** Flag indicating that crypto was requested. */
+    boolean isCrypto = false;
+}
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/OperationReason.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/OperationReason.aidl
new file mode 100644
index 0000000..abc25ed
--- /dev/null
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/OperationReason.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.biometrics.common;
+
+@VintfStability
+@Backing(type="byte")
+enum OperationReason {
+    /**
+     * A normal operation without an explicit reason.
+     */
+    UNKNOWN,
+
+    /**
+     * An operation associated with biometric prompt. This may be due to either application or
+     * system use, but it is not related to KEYGUARD device entry.
+     */
+    BIOMETRIC_PROMPT,
+
+    /**
+     * An operation associated with device entry.
+     */
+    KEYGUARD,
+}
diff --git a/biometrics/face/aidl/Android.bp b/biometrics/face/aidl/Android.bp
index 3f53fc8..fff2c1d 100644
--- a/biometrics/face/aidl/Android.bp
+++ b/biometrics/face/aidl/Android.bp
@@ -16,7 +16,7 @@
     imports: [
         "android.hardware.biometrics.common",
         "android.hardware.common-V2",
-        "android.hardware.keymaster",
+        "android.hardware.keymaster-V3",
     ],
     stability: "vintf",
     backend: {
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
index 7817864..4b51bb1 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
@@ -48,4 +48,7 @@
   void invalidateAuthenticatorId();
   void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat);
   void close();
+  android.hardware.biometrics.common.ICancellationSignal authenticateWithContext(in long operationId, in android.hardware.biometrics.common.OperationContext context);
+  android.hardware.biometrics.common.ICancellationSignal enrollWithContext(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.EnrollmentType type, in android.hardware.biometrics.face.Feature[] features, in @nullable android.hardware.common.NativeHandle previewSurface, in android.hardware.biometrics.common.OperationContext context);
+  android.hardware.biometrics.common.ICancellationSignal detectInteractionWithContext(in android.hardware.biometrics.common.OperationContext context);
 }
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
index 5f06b40..bbe3632 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
@@ -17,6 +17,7 @@
 package android.hardware.biometrics.face;
 
 import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.common.OperationContext;
 import android.hardware.biometrics.face.EnrollmentStageConfig;
 import android.hardware.biometrics.face.EnrollmentType;
 import android.hardware.biometrics.face.Feature;
@@ -441,4 +442,23 @@
      *   - ISessionCallback#onSessionClosed
      */
     void close();
+
+    /**
+     * These are alternative methods for some operations to allow the HAL to make optional
+     * optimizations during execution.
+     *
+     * HALs may ignore the additional context and treat all *WithContext methods the same as
+     * the original methods.
+     */
+
+    /* See ISession#authenticateWithContext(long) */
+    ICancellationSignal authenticateWithContext(in long operationId, in OperationContext context);
+
+    /* See ISession#enroll(HardwareAuthToken, EnrollmentType, Feature[], NativeHandle) */
+    ICancellationSignal enrollWithContext(in HardwareAuthToken hat, in EnrollmentType type,
+            in Feature[] features, in @nullable NativeHandle previewSurface,
+            in OperationContext context);
+
+    /* See ISession#detectInteraction() */
+    ICancellationSignal detectInteractionWithContext(in OperationContext context);
 }
diff --git a/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp
index 5092318..7f66eca 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",
-        "android.hardware.biometrics.common-V1-ndk",
+        "android.hardware.biometrics.face-V2-ndk",
+        "android.hardware.biometrics.common-V2-ndk",
     ],
     srcs: [
         "main.cpp",
diff --git a/biometrics/face/aidl/default/Session.cpp b/biometrics/face/aidl/default/Session.cpp
index 01cb620..9e753e5 100644
--- a/biometrics/face/aidl/default/Session.cpp
+++ b/biometrics/face/aidl/default/Session.cpp
@@ -151,4 +151,25 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Session::authenticateWithContext(
+        int64_t operationId, const common::OperationContext& /*context*/,
+        std::shared_ptr<common::ICancellationSignal>* out) {
+    return authenticate(operationId, out);
+}
+
+ndk::ScopedAStatus Session::enrollWithContext(const keymaster::HardwareAuthToken& hat,
+                                              EnrollmentType enrollmentType,
+                                              const std::vector<Feature>& features,
+                                              const std::optional<NativeHandle>& previewSurface,
+                                              const common::OperationContext& /*context*/,
+                                              std::shared_ptr<common::ICancellationSignal>* out) {
+    return enroll(hat, enrollmentType, features, previewSurface, out);
+}
+
+ndk::ScopedAStatus Session::detectInteractionWithContext(
+        const common::OperationContext& /*context*/,
+        std::shared_ptr<common::ICancellationSignal>* out) {
+    return detectInteraction(out);
+}
+
 }  // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/Session.h b/biometrics/face/aidl/default/Session.h
index 4152909..0ce9e20 100644
--- a/biometrics/face/aidl/default/Session.h
+++ b/biometrics/face/aidl/default/Session.h
@@ -68,6 +68,20 @@
 
     ndk::ScopedAStatus close() override;
 
+    ndk::ScopedAStatus authenticateWithContext(
+            int64_t operationId, const common::OperationContext& context,
+            std::shared_ptr<common::ICancellationSignal>* out) override;
+
+    ndk::ScopedAStatus enrollWithContext(
+            const keymaster::HardwareAuthToken& hat, EnrollmentType enrollmentType,
+            const std::vector<Feature>& features, const std::optional<NativeHandle>& previewSurface,
+            const common::OperationContext& context,
+            std::shared_ptr<common::ICancellationSignal>* out) override;
+
+    ndk::ScopedAStatus detectInteractionWithContext(
+            const common::OperationContext& context,
+            std::shared_ptr<common::ICancellationSignal>* out) override;
+
   private:
     std::shared_ptr<ISessionCallback> cb_;
     std::mt19937 mRandom;
diff --git a/biometrics/face/aidl/default/face-default.xml b/biometrics/face/aidl/default/face-default.xml
index 6915ad0..e6ef842 100644
--- a/biometrics/face/aidl/default/face-default.xml
+++ b/biometrics/face/aidl/default/face-default.xml
@@ -1,6 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.biometrics.face</name>
+        <version>2</version>
         <fqname>IFace/default</fqname>
     </hal>
 </manifest>
diff --git a/biometrics/face/aidl/vts/Android.bp b/biometrics/face/aidl/vts/Android.bp
index 09ec4d0..4171ac3 100644
--- a/biometrics/face/aidl/vts/Android.bp
+++ b/biometrics/face/aidl/vts/Android.bp
@@ -15,8 +15,8 @@
     ],
     srcs: ["VtsHalBiometricsFaceTargetTest.cpp"],
     static_libs: [
-        "android.hardware.biometrics.common-V1-ndk",
-        "android.hardware.biometrics.face-V1-ndk",
+        "android.hardware.biometrics.common-V2-ndk",
+        "android.hardware.biometrics.face-V2-ndk",
         "android.hardware.common-V2-ndk",
         "android.hardware.keymaster-V3-ndk",
     ],
diff --git a/biometrics/fingerprint/aidl/Android.bp b/biometrics/fingerprint/aidl/Android.bp
index c46150e..c3a056c 100644
--- a/biometrics/fingerprint/aidl/Android.bp
+++ b/biometrics/fingerprint/aidl/Android.bp
@@ -15,7 +15,7 @@
     ],
     imports: [
         "android.hardware.biometrics.common",
-        "android.hardware.keymaster",
+        "android.hardware.keymaster-V3",
     ],
     stability: "vintf",
     backend: {
@@ -26,8 +26,5 @@
             enabled: false,
         },
     },
-    versions: [
-        "1",
-        "2",
-    ],
+    versions: ["1"],
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/.hash b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/.hash
deleted file mode 100644
index 411cb75..0000000
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/.hash
+++ /dev/null
@@ -1 +0,0 @@
-762eb38ce93ea3c7d39a680949cbdbd2371b3f06
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/IFingerprint.aidl
deleted file mode 100644
index 5d3df6f..0000000
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/IFingerprint.aidl
+++ /dev/null
@@ -1,39 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-interface IFingerprint {
-  android.hardware.biometrics.fingerprint.SensorProps[] getSensorProps();
-  android.hardware.biometrics.fingerprint.ISession createSession(in int sensorId, in int userId, in android.hardware.biometrics.fingerprint.ISessionCallback cb);
-}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/ISession.aidl
deleted file mode 100644
index 9934a76..0000000
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/ISession.aidl
+++ /dev/null
@@ -1,51 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-interface ISession {
-  void generateChallenge();
-  void revokeChallenge(in long challenge);
-  android.hardware.biometrics.common.ICancellationSignal enroll(in android.hardware.keymaster.HardwareAuthToken hat);
-  android.hardware.biometrics.common.ICancellationSignal authenticate(in long operationId);
-  android.hardware.biometrics.common.ICancellationSignal detectInteraction();
-  void enumerateEnrollments();
-  void removeEnrollments(in int[] enrollmentIds);
-  void getAuthenticatorId();
-  void invalidateAuthenticatorId();
-  void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat);
-  void close();
-  void onPointerDown(in int pointerId, in int x, in int y, in float minor, in float major);
-  void onPointerUp(in int pointerId);
-  void onUiReady();
-}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
deleted file mode 100644
index 3c40ad6..0000000
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
+++ /dev/null
@@ -1,53 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-interface ISessionCallback {
-  void onChallengeGenerated(in long challenge);
-  void onChallengeRevoked(in long challenge);
-  void onAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfo info, in int vendorCode);
-  void onError(in android.hardware.biometrics.fingerprint.Error error, in int vendorCode);
-  void onEnrollmentProgress(in int enrollmentId, int remaining);
-  void onAuthenticationSucceeded(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat);
-  void onAuthenticationFailed();
-  void onLockoutTimed(in long durationMillis);
-  void onLockoutPermanent();
-  void onLockoutCleared();
-  void onInteractionDetected();
-  void onEnrollmentsEnumerated(in int[] enrollmentIds);
-  void onEnrollmentsRemoved(in int[] enrollmentIds);
-  void onAuthenticatorIdRetrieved(in long authenticatorId);
-  void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
-  void onSessionClosed();
-}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorProps.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorProps.aidl
deleted file mode 100644
index 782d289..0000000
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorProps.aidl
+++ /dev/null
@@ -1,44 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-parcelable SensorProps {
-  android.hardware.biometrics.common.CommonProps commonProps;
-  android.hardware.biometrics.fingerprint.FingerprintSensorType sensorType = android.hardware.biometrics.fingerprint.FingerprintSensorType.UNKNOWN;
-  android.hardware.biometrics.fingerprint.SensorLocation[] sensorLocations;
-  boolean supportsNavigationGestures;
-  boolean supportsDetectInteraction;
-  boolean halHandlesDisplayTouches;
-  boolean halControlsIllumination;
-}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
index 9934a76..4e7b3b4 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -48,4 +48,9 @@
   void onPointerDown(in int pointerId, in int x, in int y, in float minor, in float major);
   void onPointerUp(in int pointerId);
   void onUiReady();
+  android.hardware.biometrics.common.ICancellationSignal authenticateWithContext(in long operationId, in android.hardware.biometrics.common.OperationContext context);
+  android.hardware.biometrics.common.ICancellationSignal enrollWithContext(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.common.OperationContext context);
+  android.hardware.biometrics.common.ICancellationSignal detectInteractionWithContext(in android.hardware.biometrics.common.OperationContext context);
+  void onPointerDownWithContext(in android.hardware.biometrics.fingerprint.PointerContext context);
+  void onPointerUpWithContext(in android.hardware.biometrics.fingerprint.PointerContext context);
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/PointerContext.aidl
similarity index 91%
rename from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
rename to biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/PointerContext.aidl
index 295fde9..e383330 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/PointerContext.aidl
@@ -33,10 +33,11 @@
 
 package android.hardware.biometrics.fingerprint;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable PointerContext {
+  int pointerId = 0;
+  int x = 0;
+  int y = 0;
+  float minor = 0.000000f;
+  float major = 0.000000f;
+  boolean isAoD = false;
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
index f1d96d3..ea8c6aa 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -17,6 +17,8 @@
 package android.hardware.biometrics.fingerprint;
 
 import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.fingerprint.PointerContext;
 import android.hardware.keymaster.HardwareAuthToken;
 
 /**
@@ -140,7 +142,7 @@
      *
      * @param hat See above documentation.
      * @return ICancellationSignal An object that can be used by the framework to cancel this
-     * operation.
+     *                             operation.
      */
     ICancellationSignal enroll(in HardwareAuthToken hat);
 
@@ -234,7 +236,7 @@
      *   - ISessionCallback#onAcquired
      *
      * @return ICancellationSignal An object that can be used by the framework to cancel this
-     * operation.
+     *                             operation.
      */
     ICancellationSignal detectInteraction();
 
@@ -448,4 +450,27 @@
      * HAL, the framework will invoke this operation to notify when the illumination is showing.
      */
     void onUiReady();
+
+    /**
+     * These are alternative methods for some operations to allow the HAL to make optional
+     * optimizations during execution.
+     *
+     * HALs may ignore the additional context and treat all *WithContext methods the same as
+     * the original methods.
+     */
+
+    /** See ISession#authenticate(long) */
+    ICancellationSignal authenticateWithContext(in long operationId, in OperationContext context);
+
+    /** See ISession#enroll(HardwareAuthToken) */
+    ICancellationSignal enrollWithContext(in HardwareAuthToken hat, in OperationContext context);
+
+    /** See ISession#detectInteraction() */
+    ICancellationSignal detectInteractionWithContext(in OperationContext context);
+
+    /** See ISession#onPointerDown(int, int, int, float, float) */
+    void onPointerDownWithContext(in PointerContext context);
+
+    /** See ISession#onPointerUp(int) */
+    void onPointerUpWithContext(in PointerContext context);
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/PointerContext.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/PointerContext.aidl
new file mode 100644
index 0000000..4975175
--- /dev/null
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/PointerContext.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.biometrics.fingerprint;
+
+/**
+ * Additional context associated with a pointer event.
+ */
+@VintfStability
+parcelable PointerContext {
+    /* See android.view.MotionEvent#getPointerId. */
+    int pointerId = 0;
+
+    /* The distance in pixels from the left edge of the display. */
+    int x = 0;
+
+    /* The distance in pixels from the top edge of the display. */
+    int y = 0;
+
+    /* See android.view.MotionEvent#getTouchMinor. */
+    float minor = 0f;
+
+    /* See android.view.MotionEvent#getTouchMajor. */
+    float major = 0f;
+
+    /* Flag indicating that the display is in AoD mode. */
+    boolean isAoD = false;
+}
diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp
index d4194a3..430bf3c 100644
--- a/biometrics/fingerprint/aidl/default/Android.bp
+++ b/biometrics/fingerprint/aidl/default/Android.bp
@@ -25,7 +25,7 @@
         "libbase",
         "libbinder_ndk",
         "android.hardware.biometrics.fingerprint-V2-ndk",
-        "android.hardware.biometrics.common-V1-ndk",
+        "android.hardware.biometrics.common-V2-ndk",
     ],
 }
 
diff --git a/biometrics/fingerprint/aidl/default/Session.cpp b/biometrics/fingerprint/aidl/default/Session.cpp
index ca481e7..8cbcfc7 100644
--- a/biometrics/fingerprint/aidl/default/Session.cpp
+++ b/biometrics/fingerprint/aidl/default/Session.cpp
@@ -244,4 +244,30 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Session::authenticateWithContext(
+        int64_t operationId, const common::OperationContext& /*context*/,
+        std::shared_ptr<common::ICancellationSignal>* out) {
+    return authenticate(operationId, out);
+}
+
+ndk::ScopedAStatus Session::enrollWithContext(const keymaster::HardwareAuthToken& hat,
+                                              const common::OperationContext& /*context*/,
+                                              std::shared_ptr<common::ICancellationSignal>* out) {
+    return enroll(hat, out);
+}
+
+ndk::ScopedAStatus Session::detectInteractionWithContext(
+        const common::OperationContext& /*context*/,
+        std::shared_ptr<common::ICancellationSignal>* out) {
+    return detectInteraction(out);
+}
+
+ndk::ScopedAStatus Session::onPointerDownWithContext(const PointerContext& context) {
+    return onPointerDown(context.pointerId, context.x, context.y, context.minor, context.major);
+}
+
+ndk::ScopedAStatus Session::onPointerUpWithContext(const PointerContext& context) {
+    return onPointerUp(context.pointerId);
+}
+
 }  // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/include/Session.h b/biometrics/fingerprint/aidl/default/include/Session.h
index 9e46422..584cb27 100644
--- a/biometrics/fingerprint/aidl/default/include/Session.h
+++ b/biometrics/fingerprint/aidl/default/include/Session.h
@@ -79,6 +79,22 @@
 
     ndk::ScopedAStatus onUiReady() override;
 
+    ndk::ScopedAStatus authenticateWithContext(
+            int64_t operationId, const common::OperationContext& context,
+            std::shared_ptr<common::ICancellationSignal>* out) override;
+
+    ndk::ScopedAStatus enrollWithContext(
+            const keymaster::HardwareAuthToken& hat, const common::OperationContext& context,
+            std::shared_ptr<common::ICancellationSignal>* out) override;
+
+    ndk::ScopedAStatus detectInteractionWithContext(
+            const common::OperationContext& context,
+            std::shared_ptr<common::ICancellationSignal>* out) override;
+
+    ndk::ScopedAStatus onPointerDownWithContext(const PointerContext& context) override;
+
+    ndk::ScopedAStatus onPointerUpWithContext(const PointerContext& context) override;
+
     bool isClosed();
 
   private:
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
index 12eed55..5107240 100644
--- a/bluetooth/audio/aidl/Android.bp
+++ b/bluetooth/audio/aidl/Android.bp
@@ -43,6 +43,10 @@
             vndk: {
                 enabled: true,
             },
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.bluetooth",
+            ],
         },
     },
 }
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
index ad44c26..899b8ca 100644
--- 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
@@ -34,9 +34,9 @@
 package android.hardware.bluetooth.audio;
 @VintfStability
 parcelable AacCapabilities {
-  android.hardware.bluetooth.audio.AacObjectType objectType;
+  android.hardware.bluetooth.audio.AacObjectType[] objectType;
   int[] sampleRateHz;
-  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  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/AacObjectType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl
index c129c66..2148244 100644
--- 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
@@ -34,8 +34,8 @@
 package android.hardware.bluetooth.audio;
 @Backing(type="byte") @VintfStability
 enum AacObjectType {
-  MPEG2_LC = 1,
-  MPEG4_LC = 2,
-  MPEG4_LTP = 4,
-  MPEG4_SCALABLE = 8,
+  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/AptxCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl
index 4767b69..08a38e2 100644
--- 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
@@ -35,6 +35,6 @@
 @VintfStability
 parcelable AptxCapabilities {
   int[] sampleRateHz;
-  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  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/ChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl
index 3ca93c3..c3bc741 100644
--- 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
@@ -34,7 +34,7 @@
 package android.hardware.bluetooth.audio;
 @Backing(type="byte") @VintfStability
 enum ChannelMode {
-  UNKNOWN = 1,
-  MONO = 2,
-  STEREO = 4,
+  UNKNOWN = 0,
+  MONO = 1,
+  STEREO = 2,
 }
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
index 19e041a..aa4e4c8 100644
--- 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
@@ -35,7 +35,7 @@
 @VintfStability
 parcelable LdacCapabilities {
   int[] sampleRateHz;
-  android.hardware.bluetooth.audio.LdacChannelMode channelMode;
-  android.hardware.bluetooth.audio.LdacQualityIndex qualityIndex;
+  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
index a9d6c5e..88d6faf 100644
--- 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
@@ -34,8 +34,8 @@
 package android.hardware.bluetooth.audio;
 @Backing(type="byte") @VintfStability
 enum LdacChannelMode {
-  UNKNOWN = 1,
-  STEREO = 2,
-  DUAL = 4,
-  MONO = 8,
+  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/LdacQualityIndex.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
index 693392f..35e4358 100644
--- 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
@@ -34,8 +34,8 @@
 package android.hardware.bluetooth.audio;
 @Backing(type="byte") @VintfStability
 enum LdacQualityIndex {
-  HIGH = 1,
-  MID = 2,
-  LOW = 4,
-  ABR = 8,
+  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/PcmCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl
index 6cfe5cd..0c2f87d 100644
--- 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
@@ -35,7 +35,7 @@
 @VintfStability
 parcelable PcmCapabilities {
   int[] sampleRateHz;
-  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  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/SbcAllocMethod.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
index 5170f16..091f6d7 100644
--- 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
@@ -34,6 +34,6 @@
 package android.hardware.bluetooth.audio;
 @Backing(type="byte") @VintfStability
 enum SbcAllocMethod {
-  ALLOC_MD_S = 1,
-  ALLOC_MD_L = 2,
+  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
index ec3aa0f..c8d7e7e 100644
--- 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
@@ -35,10 +35,10 @@
 @VintfStability
 parcelable SbcCapabilities {
   int[] sampleRateHz;
-  android.hardware.bluetooth.audio.SbcChannelMode channelMode;
+  android.hardware.bluetooth.audio.SbcChannelMode[] channelMode;
   byte[] blockLength;
   byte[] numSubbands;
-  android.hardware.bluetooth.audio.SbcAllocMethod allocMethod;
+  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
index 88fca4a..6441a99 100644
--- 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
@@ -34,9 +34,9 @@
 package android.hardware.bluetooth.audio;
 @Backing(type="byte") @VintfStability
 enum SbcChannelMode {
-  UNKNOWN = 1,
-  JOINT_STEREO = 2,
-  STEREO = 4,
-  DUAL = 8,
-  MONO = 16,
+  UNKNOWN = 0,
+  JOINT_STEREO = 1,
+  STEREO = 2,
+  DUAL = 3,
+  MONO = 4,
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl
index 4303883..c4153e9 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl
@@ -24,11 +24,9 @@
  */
 @VintfStability
 parcelable AacCapabilities {
-    /* bitfield */
-    AacObjectType objectType;
+    AacObjectType[] objectType;
     int[] sampleRateHz;
-    /* bitfield */
-    ChannelMode channelMode;
+    ChannelMode[] channelMode;
     boolean variableBitRateSupported;
     byte[] bitsPerSample;
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl
index 480e422..4e9958c 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl
@@ -22,17 +22,17 @@
     /**
      * MPEG-2 Low Complexity. Support is Mandatory.
      */
-    MPEG2_LC = 1,
+    MPEG2_LC,
     /**
      * MPEG-4 Low Complexity. Support is Optional.
      */
-    MPEG4_LC = 1 << 1,
+    MPEG4_LC,
     /**
      * MPEG-4 Long Term Prediction. Support is Optional.
      */
-    MPEG4_LTP = 1 << 2,
+    MPEG4_LTP,
     /**
      * MPEG-4 Scalable. Support is Optional.
      */
-    MPEG4_SCALABLE = 1 << 3,
+    MPEG4_SCALABLE,
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl
index 6a37fc6..f5605d3 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl
@@ -24,7 +24,6 @@
 @VintfStability
 parcelable AptxCapabilities {
     int[] sampleRateHz;
-    /* bitfield */
-    ChannelMode channelMode;
+    ChannelMode[] channelMode;
     byte[] bitsPerSample;
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl
index 2df879d..6613872 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl
@@ -19,7 +19,7 @@
 @VintfStability
 @Backing(type="byte")
 enum ChannelMode {
-    UNKNOWN = 1,
-    MONO = 1 << 1,
-    STEREO = 1 << 2,
+    UNKNOWN,
+    MONO,
+    STEREO,
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl
index 44cca7e..1dbec08 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl
@@ -26,9 +26,7 @@
 @VintfStability
 parcelable LdacCapabilities {
     int[] sampleRateHz;
-    /* bitfiled */
-    LdacChannelMode channelMode;
-    /* bitfiled */
-    LdacQualityIndex qualityIndex;
+    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
index 3acca32..3cc910f 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl
@@ -22,8 +22,8 @@
 @VintfStability
 @Backing(type="byte")
 enum LdacChannelMode {
-    UNKNOWN = 1,
-    STEREO = 1 << 1,
-    DUAL = 1 << 2,
-    MONO = 1 << 3,
+    UNKNOWN,
+    STEREO,
+    DUAL,
+    MONO,
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
index cb12583..9993b8b 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
@@ -22,17 +22,17 @@
     /**
      * 990kbps
      */
-    HIGH = 1,
+    HIGH,
     /**
      * 660kbps
      */
-    MID = 1 << 1,
+    MID,
     /**
      * 330kbps
      */
-    LOW = 1 << 2,
+    LOW,
     /**
      * Adaptive Bit Rate mode
      */
-    ABR = 1 << 3,
+    ABR,
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl
index f5d699e..776b777 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl
@@ -24,7 +24,7 @@
 @VintfStability
 parcelable PcmCapabilities {
     int[] sampleRateHz;
-    ChannelMode channelMode;
+    ChannelMode[] channelMode;
     byte[] bitsPerSample;
     /**
      * Data interval for data transfer
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
index 7047e34..1159f30 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
@@ -22,9 +22,9 @@
     /**
      * SNR
      */
-    ALLOC_MD_S = 1,
+    ALLOC_MD_S,
     /**
      * Loudness
      */
-    ALLOC_MD_L = 1 << 1,
+    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
index cf62ed4..743a1f7 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl
@@ -25,12 +25,10 @@
 @VintfStability
 parcelable SbcCapabilities {
     int[] sampleRateHz;
-    /* bitfield */
-    SbcChannelMode channelMode;
+    SbcChannelMode[] channelMode;
     byte[] blockLength;
     byte[] numSubbands;
-    /* bitfield */
-    SbcAllocMethod allocMethod;
+    SbcAllocMethod[] allocMethod;
     byte[] bitsPerSample;
     /*
      * range from 2 to 250.
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl
index 7eb38cd..68e3267 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl
@@ -19,9 +19,9 @@
 @VintfStability
 @Backing(type="byte")
 enum SbcChannelMode {
-    UNKNOWN = 1,
-    JOINT_STEREO = 1 << 1,
-    STEREO = 1 << 2,
-    DUAL = 1 << 3,
-    MONO = 1 << 4,
+    UNKNOWN,
+    JOINT_STEREO,
+    STEREO,
+    DUAL,
+    MONO,
 }
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
new file mode 100644
index 0000000..fc8a911
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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 {
+
+A2dpOffloadAudioProvider::A2dpOffloadAudioProvider() {
+  session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+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, 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,
+                                              _aidl_return);
+}
+
+ndk::ScopedAStatus A2dpOffloadAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  *_aidl_return = DataMQDesc();
+  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+                                                nullptr, *audio_config_);
+  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/A2dpOffloadAudioProvider.h b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
new file mode 100644
index 0000000..5934f5b
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "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, DataMQDesc* _aidl_return);
+
+ private:
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+}  // 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..7e49074
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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;
+
+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);
+    session_type_ = SessionType::A2DP_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 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, 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,
+                                              _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();
+  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+                                                _aidl_return, *audio_config_);
+  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/A2dpSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
new file mode 100644
index 0000000..3bc0a13
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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, 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/Android.bp b/bluetooth/audio/aidl/default/Android.bp
new file mode 100644
index 0000000..846702f
--- /dev/null
+++ b/bluetooth/audio/aidl/default/Android.bp
@@ -0,0 +1,34 @@
+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-V1-impl",
+    vendor: true,
+    vintf_fragments: ["bluetooth_audio.xml"],
+    srcs: [
+        "BluetoothAudioProvider.cpp",
+        "BluetoothAudioProviderFactory.cpp",
+        "A2dpOffloadAudioProvider.cpp",
+        "A2dpSoftwareAudioProvider.cpp",
+        "HearingAidAudioProvider.cpp",
+        "LeAudioOffloadAudioProvider.cpp",
+        "LeAudioSoftwareAudioProvider.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..c2ffa2e
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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, DataMQDesc* _aidl_return) {
+  if (host_if == nullptr) {
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+  stack_iface_ = host_if;
+
+  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_);
+
+    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();
+}
+
+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->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..f7acbdf
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProvider.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, DataMQDesc* _aidl_return);
+  ndk::ScopedAStatus endSession();
+  ndk::ScopedAStatus streamStarted(BluetoothAudioStatus status);
+  ndk::ScopedAStatus streamSuspended(BluetoothAudioStatus status);
+  ndk::ScopedAStatus updateAudioConfiguration(
+      const AudioConfiguration& audio_config);
+
+  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_;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
new file mode 100644
index 0000000..8e6cee7
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "BTAudioProvidersFactory"
+
+#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<A2dpSoftwareAudioProvider>();
+      break;
+    case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<A2dpOffloadAudioProvider>();
+      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;
+    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) {
+    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) {
+    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..96d888c
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProviderFactory.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 {
+
+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..a993059
--- /dev/null
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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, 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,
+                                              _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);
+  }
+  auto desc = data_mq_->dupeDesc();
+  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+                                                &desc, *audio_config_);
+  *_aidl_return = data_mq_->dupeDesc();
+  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/HearingAidAudioProvider.h b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
new file mode 100644
index 0000000..a7e19e9
--- /dev/null
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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, 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..4078783
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderLeAudioSW"
+
+#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;
+}
+
+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, 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,
+                                              _aidl_return);
+}
+
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+                                                nullptr, *audio_config_);
+  *_aidl_return = DataMQDesc();
+  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/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
new file mode 100644
index 0000000..a27a2e7
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.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 "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, DataMQDesc* _aidl_return);
+
+ private:
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+  LeAudioOffloadOutputAudioProvider();
+};
+
+class LeAudioOffloadInputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+  LeAudioOffloadInputAudioProvider();
+};
+
+}  // 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..f9962fd
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "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;
+}
+
+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, 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)
+    buffer_modifier = kBufferOutCount;
+  else if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH)
+    buffer_modifier = kBufferInCount;
+
+  uint32_t data_mq_size =
+      (ceil(pcm_config.sampleRateHz) / 1000) *
+      channel_mode_to_channel_count(pcm_config.channelMode) *
+      (pcm_config.bitsPerSample / 8) * (pcm_config.dataIntervalUs / 1000) *
+      buffer_modifier;
+
+  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,
+                                              _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();
+  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+                                                _aidl_return, *audio_config_);
+  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/LeAudioSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
new file mode 100644
index 0000000..fa58182
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "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, 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();
+};
+
+}  // 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/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 4f712bf..974357e 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -32,5 +32,30 @@
         "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",
+        "android.hardware.bluetooth.audio@2.2",
+        "libbase",
+        "libcutils",
+        "libbinder_ndk",
+        "libfmq",
+        "liblog",
+        "android.hardware.bluetooth.audio-V1-ndk",
+        "libhidlbase",
     ],
 }
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
new file mode 100644
index 0000000..92cd0f5
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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, 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 kDefaultOffloadLc3Capability = {
+    .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 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_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 = {std::make_tuple(stereoAudio, 2, 1),
+                              std::make_tuple(monoAudio, 1, 2),
+                              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(kDefaultOffloadLc3Capability.samplingFrequencyHz,
+                        lc3_data.samplingFrequencyHz) &&
+      ContainedInVector(kDefaultOffloadLc3Capability.frameDurationUs,
+                        lc3_data.frameDurationUs) &&
+      ContainedInVector(kDefaultOffloadLc3Capability.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) {
+    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) {
+    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>(
+                kDefaultOffloadLc3Capability);
+        break;
+      case CodecType::UNKNOWN:
+        codec_capability = {};
+        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) {
+    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::UNKNOWN:
+      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) {
+    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
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
new file mode 100644
index 0000000..c542ce5
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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 Lc3Configuration& codec_config);
+
+  static bool IsOffloadLeAudioConfigurationValid(
+      const SessionType& session_type,
+      const LeAudioConfiguration& codec_config);
+
+  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);
+  static bool IsOffloadLeAudioConfigurationValid(
+      const SessionType& session_type, const LeAudioCodecConfiguration&);
+};
+
+}  // 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..95e473e
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -0,0 +1,581 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
+
+const CodecConfiguration BluetoothAudioSession::kInvalidCodecConfiguration = {};
+const LeAudioConfiguration kInvalidLeAudioConfiguration = {};
+AudioConfiguration BluetoothAudioSession::invalidSoftwareAudioConfiguration =
+    {};
+AudioConfiguration BluetoothAudioSession::invalidOffloadAudioConfiguration = {};
+AudioConfiguration BluetoothAudioSession::invalidLeOffloadAudioConfig = {};
+
+BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
+    : session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {
+  invalidSoftwareAudioConfiguration.set<AudioConfiguration::pcmConfig>(
+      kInvalidPcmConfiguration);
+  invalidOffloadAudioConfiguration.set<AudioConfiguration::a2dpConfig>(
+      kInvalidCodecConfiguration);
+  invalidLeOffloadAudioConfig.set<AudioConfiguration::leAudioConfig>(
+      kInvalidLeAudioConfiguration);
+}
+
+/***
+ *
+ * Callback methods
+ *
+ ***/
+
+void BluetoothAudioSession::OnSessionStarted(
+    const std::shared_ptr<IBluetoothAudioPort> stack_iface,
+    const DataMQDesc* mq_desc, const AudioConfiguration& audio_config) {
+  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";
+    if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+      audio_config_ = std::make_unique<AudioConfiguration>(
+          invalidOffloadAudioConfiguration);
+    } else {
+      audio_config_ = std::make_unique<AudioConfiguration>(
+          invalidSoftwareAudioConfiguration);
+    }
+  } else {
+    stack_iface_ = stack_iface;
+    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_);
+  if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+    audio_config_ =
+        std::make_unique<AudioConfiguration>(invalidOffloadAudioConfiguration);
+  } else {
+    audio_config_ =
+        std::make_unique<AudioConfiguration>(invalidSoftwareAudioConfiguration);
+  }
+  stack_iface_ = nullptr;
+  UpdateDataPath(nullptr);
+  if (toggled) {
+    ReportSessionStatus();
+  }
+}
+
+/***
+ *
+ * Util methods
+ *
+ ***/
+
+const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+      return invalidOffloadAudioConfiguration;
+    } else {
+      return invalidSoftwareAudioConfiguration;
+    }
+    switch (session_type_) {
+      case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+        return invalidOffloadAudioConfiguration;
+      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+        return invalidLeOffloadAudioConfig;
+      default:
+        return invalidSoftwareAudioConfiguration;
+    }
+  }
+  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 ||
+       (data_mq_ != nullptr && data_mq_->isValid()));
+  return stack_iface_ != nullptr && is_mq_valid;
+}
+
+/***
+ *
+ * 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() {
+  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();
+  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);
+  bool is_offload_a2dp_session =
+      (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_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);
+  }
+}
+
+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) {
+    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) {
+    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";
+  }
+}
+
+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
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
new file mode 100644
index 0000000..85fd571
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/SessionType.h>
+#include <fmq/AidlMessageQueue.h>
+#include <hardware/audio.h>
+
+#include <mutex>
+#include <unordered_map>
+
+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_;
+};
+
+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);
+
+  /***
+   * 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);
+
+  /***
+   * Those control functions are for the bluetooth_audio module to start,
+   * suspend, stop stream, to check position, and to update metadata.
+   ***/
+  bool StartStream();
+  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);
+
+  // 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();
+
+  static constexpr PcmConfiguration kInvalidPcmConfiguration = {};
+  // can't be constexpr because of non-literal type
+  static const CodecConfiguration kInvalidCodecConfiguration;
+
+  static AudioConfiguration invalidSoftwareAudioConfiguration;
+  static AudioConfiguration invalidOffloadAudioConfiguration;
+  static AudioConfiguration invalidLeOffloadAudioConfig;
+
+ 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_;
+
+  // 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
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
new file mode 100644
index 0000000..a3ed428
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
@@ -0,0 +1,182 @@
+/*
+ * 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();
+    } else if (session_type ==
+               SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+      return BluetoothAudioSession::invalidOffloadAudioConfiguration;
+    } else {
+      return BluetoothAudioSession::invalidSoftwareAudioConfiguration;
+    }
+  }
+
+  /***
+   * 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) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->StartStream();
+    }
+    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);
+    }
+  }
+
+  /***
+   * 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
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h
new file mode 100644
index 0000000..18569c3
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->OnSessionStarted(host_iface, data_mq, audio_config);
+    }
+  }
+
+  /***
+   * 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);
+    }
+  }
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
new file mode 100644
index 0000000..91e0238
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
@@ -0,0 +1,775 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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"
+#include "HidlToAidlMiddleware_2_2.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;
+
+using LeAudioConfig_2_2 =
+    ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration;
+using LeAudioMode_2_2 =
+    ::android::hardware::bluetooth::audio::V2_2::LeAudioMode;
+
+std::mutex legacy_callback_lock;
+std::unordered_map<
+    SessionType,
+    std::unordered_map<uint16_t, std::shared_ptr<PortStatusCallbacks_2_2>>>
+    legacy_callback_table;
+
+const static std::unordered_map<SessionType_2_0, SessionType>
+    session_type_2_0_to_aidl_map{
+        {SessionType_2_0::A2DP_SOFTWARE_ENCODING_DATAPATH,
+         SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH},
+        {SessionType_2_0::A2DP_HARDWARE_OFFLOAD_DATAPATH,
+         SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH},
+        {SessionType_2_0::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+         SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH},
+    };
+
+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_0>
+    sample_rate_to_hidl_2_0_map{
+        {44100, SampleRate_2_0::RATE_44100},
+        {48000, SampleRate_2_0::RATE_48000},
+        {88200, SampleRate_2_0::RATE_88200},
+        {96000, SampleRate_2_0::RATE_96000},
+        {176400, SampleRate_2_0::RATE_176400},
+        {192000, SampleRate_2_0::RATE_192000},
+        {16000, SampleRate_2_0::RATE_16000},
+        {24000, SampleRate_2_0::RATE_24000},
+    };
+
+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},
+    };
+
+const static std::unordered_map<LeAudioMode, LeAudioMode_2_2>
+    leaudio_mode_to_hidl_map{
+        {LeAudioMode::UNKNOWN, LeAudioMode_2_2::UNKNOWN},
+        {LeAudioMode::UNICAST, LeAudioMode_2_2::UNICAST},
+        {LeAudioMode::BROADCAST, LeAudioMode_2_2::BROADCAST},
+    };
+
+inline SessionType from_session_type_2_0(
+    const SessionType_2_0& session_type_hidl) {
+  auto it = session_type_2_0_to_aidl_map.find(session_type_hidl);
+  if (it != session_type_2_0_to_aidl_map.end()) return it->second;
+  return SessionType::UNKNOWN;
+}
+
+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 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_0 to_hidl_sample_rate_2_0(const int32_t sample_rate_hz) {
+  auto it = sample_rate_to_hidl_2_0_map.find(sample_rate_hz);
+  if (it != sample_rate_to_hidl_2_0_map.end()) return it->second;
+  return SampleRate_2_0::RATE_UNKNOWN;
+}
+
+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 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& leaudio_config) {
+  auto& unicast_config =
+      leaudio_config.modeConfig
+          .get<LeAudioConfiguration::LeAudioModeConfig::unicastConfig>();
+
+  auto& le_codec_config = unicast_config.leAudioCodecConfig
+                              .get<LeAudioCodecConfiguration::lc3Config>();
+
+  Lc3CodecConfig_2_1 hidl_lc3_codec_config;
+  hidl_lc3_codec_config.lc3Config = to_hidl_lc3_config_2_1(le_codec_config);
+
+  hidl_lc3_codec_config.audioChannelAllocation =
+      unicast_config.streamMap.size();
+
+  return hidl_lc3_codec_config;
+}
+
+inline LeAudioConfig_2_2 to_hidl_leaudio_config_2_2(
+    const LeAudioConfiguration& leaudio_config) {
+  LeAudioConfig_2_2 hidl_leaudio_config;
+  if (leaudio_mode_to_hidl_map.find(leaudio_config.mode) !=
+      leaudio_mode_to_hidl_map.end()) {
+    hidl_leaudio_config.mode = leaudio_mode_to_hidl_map.at(leaudio_config.mode);
+  }
+
+  if (leaudio_config.modeConfig.getTag() ==
+      LeAudioConfiguration::LeAudioModeConfig::unicastConfig) {
+    auto& unicast_config =
+        leaudio_config.modeConfig
+            .get<LeAudioConfiguration::LeAudioModeConfig::unicastConfig>();
+    ::android::hardware::bluetooth::audio::V2_2::UnicastConfig
+        hidl_unicast_config;
+    hidl_unicast_config.peerDelay =
+        static_cast<uint32_t>(unicast_config.peerDelay);
+
+    auto& lc3_config = unicast_config.leAudioCodecConfig
+                           .get<LeAudioCodecConfiguration::lc3Config>();
+    hidl_unicast_config.lc3Config = to_hidl_lc3_config_2_1(lc3_config);
+
+    hidl_unicast_config.streamMap.resize(unicast_config.streamMap.size());
+    for (int i = 0; i < unicast_config.streamMap.size(); i++) {
+      hidl_unicast_config.streamMap[i].audioChannelAllocation =
+          static_cast<uint32_t>(
+              unicast_config.streamMap[i].audioChannelAllocation);
+      hidl_unicast_config.streamMap[i].streamHandle =
+          static_cast<uint16_t>(unicast_config.streamMap[i].streamHandle);
+    }
+  } else if (leaudio_config.modeConfig.getTag() ==
+             LeAudioConfiguration::LeAudioModeConfig::broadcastConfig) {
+    auto bcast_config =
+        leaudio_config.modeConfig
+            .get<LeAudioConfiguration::LeAudioModeConfig::broadcastConfig>();
+    ::android::hardware::bluetooth::audio::V2_2::BroadcastConfig
+        hidl_bcast_config;
+    hidl_bcast_config.streamMap.resize(bcast_config.streamMap.size());
+    for (int i = 0; i < bcast_config.streamMap.size(); i++) {
+      hidl_bcast_config.streamMap[i].audioChannelAllocation =
+          static_cast<uint32_t>(
+              bcast_config.streamMap[i].audioChannelAllocation);
+      hidl_bcast_config.streamMap[i].streamHandle =
+          static_cast<uint16_t>(bcast_config.streamMap[i].streamHandle);
+      hidl_bcast_config.streamMap[i].lc3Config = to_hidl_lc3_config_2_1(
+          bcast_config.streamMap[i]
+              .leAudioCodecConfig.get<LeAudioCodecConfiguration::lc3Config>());
+    }
+  }
+  return hidl_leaudio_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;
+  }
+  return hidl_audio_config;
+}
+
+inline AudioConfig_2_2 to_hidl_audio_config_2_2(
+    const AudioConfiguration& audio_config) {
+  AudioConfig_2_2 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.leAudioConfig(to_hidl_leaudio_config_2_2(
+          audio_config.get<AudioConfiguration::leAudioConfig>()));
+      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) {
+  PortStatusCallbacks_2_2 callback_2_2{
+      .control_result_cb_ = cbacks.control_result_cb_,
+      .session_changed_cb_ = cbacks.session_changed_cb_,
+  };
+  return HidlToAidlMiddleware_2_2::RegisterControlResultCback(
+      static_cast<SessionType_2_1>(session_type), callback_2_2);
+}
+
+void HidlToAidlMiddleware_2_0::UnregisterControlResultCback(
+    const SessionType_2_0& session_type, uint16_t cookie) {
+  HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
+      static_cast<SessionType_2_1>(session_type), 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);
+}
+
+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)));
+}
+
+/***
+ *
+ * 2.2
+ *
+ ***/
+
+bool HidlToAidlMiddleware_2_2::IsSessionReady(
+    const SessionType_2_1& session_type) {
+  return BluetoothAudioSessionControl::IsSessionReady(
+      from_session_type_2_1(session_type));
+}
+
+uint16_t HidlToAidlMiddleware_2_2::RegisterControlResultCback(
+    const SessionType_2_1& session_type,
+    const PortStatusCallbacks_2_2& cbacks) {
+  LOG(INFO) << __func__ << ": " << toString(session_type);
+  auto aidl_session_type = from_session_type_2_1(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);
+        };
+  };
+  if (cbacks.audio_configuration_changed_cb_) {
+    aidl_callbacks.audio_configuration_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->audio_configuration_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_2>(cbacks);
+  }
+  return cookie;
+}
+
+void HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
+    const SessionType_2_1& session_type, uint16_t cookie) {
+  LOG(INFO) << __func__ << ": " << toString(session_type);
+  auto aidl_session_type = from_session_type_2_1(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_2 HidlToAidlMiddleware_2_2::GetAudioConfig(
+    const SessionType_2_1& session_type) {
+  return to_hidl_audio_config_2_2(BluetoothAudioSessionControl::GetAudioConfig(
+      from_session_type_2_1(session_type)));
+}
+
+bool HidlToAidlMiddleware_2_2::StartStream(
+    const SessionType_2_1& session_type) {
+  return BluetoothAudioSessionControl::StartStream(
+      from_session_type_2_1(session_type));
+}
+
+bool HidlToAidlMiddleware_2_2::SuspendStream(
+    const SessionType_2_1& session_type) {
+  return BluetoothAudioSessionControl::SuspendStream(
+      from_session_type_2_1(session_type));
+}
+
+void HidlToAidlMiddleware_2_2::StopStream(const SessionType_2_1& session_type) {
+  return BluetoothAudioSessionControl::StopStream(
+      from_session_type_2_1(session_type));
+}
+
+void HidlToAidlMiddleware_2_2::UpdateSinkMetadata(
+    const SessionType_2_1& session_type,
+    const struct sink_metadata* sink_metadata) {
+  return BluetoothAudioSessionControl::UpdateSinkMetadata(
+      from_session_type_2_1(session_type), *sink_metadata);
+}
+
+}  // 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..d10ee37
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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);
+};
+
+}  // 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/aidl_session/HidlToAidlMiddleware_2_2.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
new file mode 100644
index 0000000..149e404
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/bluetooth/audio/2.2/types.h>
+
+#include "../session/BluetoothAudioSession.h"
+#include "../session/BluetoothAudioSession_2_2.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using SessionType_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::SessionType;
+using PortStatusCallbacks_2_0 =
+    ::android::bluetooth::audio::PortStatusCallbacks;
+using PortStatusCallbacks_2_2 =
+    ::android::bluetooth::audio::PortStatusCallbacks_2_2;
+using AudioConfig_2_2 =
+    ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration;
+
+class HidlToAidlMiddleware_2_2 {
+ public:
+  static bool IsSessionReady(const SessionType_2_1& session_type);
+
+  static uint16_t RegisterControlResultCback(
+      const SessionType_2_1& session_type,
+      const PortStatusCallbacks_2_2& cbacks);
+
+  static void UnregisterControlResultCback(const SessionType_2_1& session_type,
+                                           uint16_t cookie);
+
+  static const AudioConfig_2_2 GetAudioConfig(
+      const SessionType_2_1& session_type);
+
+  static bool StartStream(const SessionType_2_1& session_type);
+
+  static bool SuspendStream(const SessionType_2_1& session_type);
+
+  static void StopStream(const SessionType_2_1& session_type);
+
+  static void UpdateSinkMetadata(const SessionType_2_1& session_type,
+                                 const struct sink_metadata* sink_metadata);
+};
+
+}  // 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..6d5608b 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;
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
index bf1f9b5..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 =
@@ -72,6 +77,7 @@
   } else {
     session_type_2_1_ = (session_type);
   }
+  raw_session_type_ = session_type;
 }
 
 std::shared_ptr<BluetoothAudioSession>
@@ -83,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
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/BluetoothAudioSession_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
index 60ac4ec..4613ddc 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
@@ -22,10 +22,15 @@
 #include <android-base/stringprintf.h>
 #include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioPort.h>
 
+#include "../aidl_session/HidlToAidlMiddleware_2_0.h"
+#include "../aidl_session/HidlToAidlMiddleware_2_2.h"
+
 namespace android {
 namespace bluetooth {
 namespace audio {
 
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_2;
 using ::android::hardware::audio::common::V5_0::AudioSource;
 using ::android::hardware::audio::common::V5_0::RecordTrackMetadata;
 using ::android::hardware::audio::common::V5_0::SinkMetadata;
@@ -93,6 +98,7 @@
   } else {
     session_type_2_1_ = (session_type);
   }
+  raw_session_type_ = session_type;
   invalidSoftwareAudioConfiguration.pcmConfig(kInvalidPcmParameters);
   invalidOffloadAudioConfiguration.codecConfig(
       audio_session->kInvalidCodecConfiguration);
@@ -100,6 +106,8 @@
 }
 
 bool BluetoothAudioSession_2_2::IsSessionReady() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::IsSessionReady(raw_session_type_);
   if (session_type_2_1_ !=
           SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
       session_type_2_1_ !=
@@ -122,6 +130,9 @@
 
 void BluetoothAudioSession_2_2::UpdateSinkMetadata(
     const struct sink_metadata* sink_metadata) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::UpdateSinkMetadata(raw_session_type_,
+                                                        sink_metadata);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
@@ -172,6 +183,8 @@
 // AudioConfiguration
 const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
 BluetoothAudioSession_2_2::GetAudioConfig() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::GetAudioConfig(raw_session_type_);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (IsSessionReady()) {
     auto audio_config_discriminator = audio_config_2_2_.getDiscriminator();
@@ -226,6 +239,8 @@
 // Those control functions are for the bluetooth_audio module to start, suspend,
 // stop stream, to check position, and to update metadata.
 bool BluetoothAudioSession_2_2::StartStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::StartStream(raw_session_type_);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
@@ -242,6 +257,8 @@
 }
 
 bool BluetoothAudioSession_2_2::SuspendStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::SuspendStream(raw_session_type_);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
@@ -258,6 +275,8 @@
 }
 
 void BluetoothAudioSession_2_2::StopStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::StopStream(raw_session_type_);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (!IsSessionReady()) {
     return;
@@ -395,6 +414,9 @@
 // @return: cookie - the assigned number to this bluetooth_audio output
 uint16_t BluetoothAudioSession_2_2::RegisterStatusCback(
     const PortStatusCallbacks_2_2& cbacks) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::RegisterControlResultCback(
+        raw_session_type_, cbacks);
   if (session_type_2_1_ !=
           SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
       session_type_2_1_ !=
@@ -432,6 +454,9 @@
 // PortStatusCallbacks_2_2
 // @param: cookie - indicates which bluetooth_audio output is
 void BluetoothAudioSession_2_2::UnregisterStatusCback(uint16_t cookie) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
+        raw_session_type_, cookie);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (session_type_2_1_ !=
           SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
index 3673fd8..b6f96ab 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
@@ -68,6 +68,7 @@
   std::shared_ptr<BluetoothAudioSession_2_1> audio_session_2_1;
 
   ::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_2::AudioConfiguration
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
index 7fcf523..fbe8686 100644
--- a/camera/common/1.0/default/HandleImporter.cpp
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -30,6 +30,7 @@
 using aidl::android::hardware::graphics::common::PlaneLayout;
 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
+using MetadataType = android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
 using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
 using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
 using MapperErrorV4 = android::hardware::graphics::mapper::V4_0::Error;
@@ -123,6 +124,21 @@
     return layout;
 }
 
+bool isMetadataPesent(const sp<IMapperV4> mapper, const buffer_handle_t& buf,
+        MetadataType metadataType) {
+    auto buffer = const_cast<native_handle_t*>(buf);
+    mapper->get(buffer, metadataType, [] (const auto& tmpError,
+                const auto& tmpMetadata) {
+                    if (tmpError == MapperErrorV4::NONE) {
+                        return tmpMetadata.size() > 0;
+                    } else {
+                        ALOGE("%s: failed to get metadata %d!", __FUNCTION__, tmpError);
+                        return false;
+                    }});
+
+    return false;
+}
+
 std::vector<PlaneLayout> getPlaneLayouts(const sp<IMapperV4> mapper, buffer_handle_t& buf) {
     auto buffer = const_cast<native_handle_t*>(buf);
     std::vector<PlaneLayout> planeLayouts;
@@ -449,6 +465,55 @@
     return -1;
 }
 
+bool HandleImporter::isSmpte2086Present(const buffer_handle_t& buf) {
+    Mutex::Autolock lock(mLock);
+
+    if (!mInitialized) {
+        initializeLocked();
+    }
+
+    if (mMapperV4 != nullptr) {
+        return isMetadataPesent(mMapperV4, buf, gralloc4::MetadataType_Smpte2086);
+    } else {
+        ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
+    }
+
+    return false;
+}
+
+bool HandleImporter::isSmpte2094_10Present(const buffer_handle_t& buf) {
+    Mutex::Autolock lock(mLock);
+
+    if (!mInitialized) {
+        initializeLocked();
+    }
+
+    if (mMapperV4 != nullptr) {
+        return isMetadataPesent(mMapperV4, buf, gralloc4::MetadataType_Smpte2094_10);
+    } else {
+        ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
+    }
+
+    return false;
+}
+
+bool HandleImporter::isSmpte2094_40Present(const buffer_handle_t& buf) {
+    Mutex::Autolock lock(mLock);
+
+    if (!mInitialized) {
+        initializeLocked();
+    }
+
+    if (mMapperV4 != nullptr) {
+        return isMetadataPesent(mMapperV4, buf, gralloc4::MetadataType_Smpte2094_40);
+    } else {
+        ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
+    }
+
+    return false;
+}
+
+
 } // namespace helper
 } // namespace V1_0
 } // namespace common
diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h
index e404439..83fa755 100644
--- a/camera/common/1.0/default/include/HandleImporter.h
+++ b/camera/common/1.0/default/include/HandleImporter.h
@@ -61,6 +61,11 @@
 
     int unlock(buffer_handle_t& buf); // returns release fence
 
+    // Query Gralloc4 metadata
+    bool isSmpte2086Present(const buffer_handle_t& buf);
+    bool isSmpte2094_10Present(const buffer_handle_t& buf);
+    bool isSmpte2094_40Present(const buffer_handle_t& buf);
+
 private:
     void initializeLocked();
     void cleanup();
diff --git a/camera/device/3.8/Android.bp b/camera/device/3.8/Android.bp
index 2a1f215..c3c2941 100644
--- a/camera/device/3.8/Android.bp
+++ b/camera/device/3.8/Android.bp
@@ -9,7 +9,6 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-
 hidl_interface {
     name: "android.hardware.camera.device@3.8",
     root: "android.hardware",
@@ -17,6 +16,7 @@
         "types.hal",
         "ICameraDevice.hal",
         "ICameraDeviceCallback.hal",
+        "ICameraDeviceSession.hal",
     ],
     interfaces: [
         "android.hardware.camera.common@1.0",
@@ -31,6 +31,7 @@
         "android.hardware.camera.metadata@3.4",
         "android.hardware.camera.metadata@3.5",
         "android.hardware.camera.metadata@3.6",
+        "android.hardware.camera.metadata@3.8",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
diff --git a/camera/device/3.8/ICameraDevice.hal b/camera/device/3.8/ICameraDevice.hal
index 1101819..8832c68 100644
--- a/camera/device/3.8/ICameraDevice.hal
+++ b/camera/device/3.8/ICameraDevice.hal
@@ -26,8 +26,8 @@
  * API at LIMITED or better hardware level.
  *
  * ICameraDevice.open() must return @3.2::ICameraDeviceSession,
- * @3.5::ICameraDeviceSession, @3.6::ICameraDeviceSession, or
- * @3.7::ICameraDeviceSession.
+ * @3.5::ICameraDeviceSession, @3.6::ICameraDeviceSession,
+ * @3.7::ICameraDeviceSession, or @3.8::ICameraDeviceSession.
  */
 interface ICameraDevice extends @3.7::ICameraDevice {
     /**
@@ -107,4 +107,15 @@
      *
      */
     getTorchStrengthLevel() generates (Status status, int32_t torchStrength);
+
+     /**
+     * isStreamCombinationSupported_3_8:
+     *
+     * Identical to @3.7::ICameraDevice.isStreamCombinationSupported, except
+     * that it takes a @3.8::StreamConfiguration parameter, which could contain
+     * additional information about a specific 10-bit dynamic range profile.
+     *
+     */
+    isStreamCombinationSupported_3_8(StreamConfiguration streams)
+            generates (Status status, bool queryStatus);
 };
diff --git a/camera/device/3.8/ICameraDeviceSession.hal b/camera/device/3.8/ICameraDeviceSession.hal
new file mode 100644
index 0000000..88e4338
--- /dev/null
+++ b/camera/device/3.8/ICameraDeviceSession.hal
@@ -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.camera.device@3.8;
+
+import android.hardware.camera.common@1.0::Status;
+import @3.5::StreamConfiguration;
+import @3.7::ICameraDeviceSession;
+import @3.6::HalStreamConfiguration;
+
+/**
+ * Camera device active session interface.
+ *
+ * Obtained via ICameraDevice::open(), this interface contains the methods to
+ * configure and request captures from an active camera device.
+ */
+interface ICameraDeviceSession extends @3.7::ICameraDeviceSession {
+    /**
+     * configureStreams_3_8:
+     *
+     * Identical to @3.7::ICameraDeviceSession.configureStreams_3_7, except that:
+     *
+     * - The requestedConfiguration allows the camera framework to configure
+     *   10-bit dynamic range profile.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On successful stream configuration.
+     *     INTERNAL_ERROR:
+     *         If there has been a fatal error and the device is no longer
+     *         operational. Only close() can be called successfully by the
+     *         framework after this error is returned.
+     *     ILLEGAL_ARGUMENT:
+     *         If the requested stream configuration is invalid. Some examples
+     *         of invalid stream configurations include:
+     *           - Including more than 1 INPUT stream
+     *           - Not including any OUTPUT streams
+     *           - Including streams with unsupported formats, or an unsupported
+     *             size for that format.
+     *           - Including too many output streams of a certain format.
+     *           - Unsupported rotation configuration
+     *           - Stream sizes/formats don't satisfy the
+     *             StreamConfigurationMode requirements
+     *             for non-NORMAL mode, or the requested operation_mode is not
+     *             supported by the HAL.
+     *           - Unsupported usage flag
+     *           - Unsupported stream groupIds, or unsupported multi-resolution
+     *             input stream.
+     *           - Invalid combination between a 10-bit dynamic range profile
+     *             and none impl. defined 8-bit format for a particular stream.
+     *         The camera service cannot filter out all possible illegal stream
+     *         configurations, since some devices may support more simultaneous
+     *         streams or larger stream resolutions than the minimum required
+     *         for a given camera device hardware level. The HAL must return an
+     *         ILLEGAL_ARGUMENT for any unsupported stream set, and then be
+     *         ready to accept a future valid stream configuration in a later
+     *         configureStreams call.
+     * @return halConfiguration The stream parameters desired by the HAL for
+     *     each stream, including maximum buffers, the usage flags, and the
+     *     override format and dataspace.
+     */
+    configureStreams_3_8(StreamConfiguration requestedConfiguration)
+        generates (Status status, @3.6::HalStreamConfiguration halConfiguration);
+
+    /**
+     * repeatingRequestEnd:
+     *
+     * Notification about the last frame number in a repeating request along with the
+     * ids of all streams included in the repeating request.
+     *
+     * This can be called at any point after 'processCaptureRequest' in response
+     * to camera clients disabling an active repeating request.
+     *
+     * Performance requirements:
+     * The call must not be blocked for extensive periods and should be extremely lightweight. There
+     * must be no frame rate degradation or frame jitter introduced.
+     *
+     * This method must always succeed, even if the device has encountered a
+     * serious error.
+     */
+    repeatingRequestEnd(uint32_t frameNumber, vec<int32_t> streamIds);
+};
diff --git a/camera/device/3.8/types.hal b/camera/device/3.8/types.hal
index 843d050..9d1ac22 100644
--- a/camera/device/3.8/types.hal
+++ b/camera/device/3.8/types.hal
@@ -19,6 +19,11 @@
 import @3.2::ErrorMsg;
 import @3.2::MsgType;
 import @3.2::ShutterMsg;
+import @3.2::CameraMetadata;
+import @3.2::StreamConfigurationMode;
+import @3.7::Stream;
+
+import android.hardware.camera.metadata@3.8::CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
 
 /**
  * ShutterMsg:
@@ -67,3 +72,75 @@
         ShutterMsg shutter;
     } msg;
 };
+
+/**
+ * Stream:
+ *
+ * A descriptor for a single camera input or output stream. A stream is defined
+ * by the framework by its buffer resolution and format, and additionally by the
+ * HAL with the gralloc usage flags and the maximum in-flight buffer count.
+ *
+ * This version extends the @3.7 Stream with the dynamic range profile field.
+ */
+struct Stream {
+    /**
+     * The definition of Stream from the prior version.
+     */
+    @3.7::Stream v3_7;
+
+    /**
+     * The dynamic range profile for this stream.
+     *
+     * This field is valid and must only be considered for streams with format
+     * android.hardware.graphics.common.PixelFormat.YCBCR_P010 or
+     * android.hardware.graphics.common.PixelFormat.IMPLEMENTATION_DEFINED on devices supporting the
+     * ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_10_BIT capability.
+     *
+     */
+    CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap dynamicRangeProfile;
+};
+
+/**
+ * StreamConfiguration:
+ *
+ * Identical to @3.7::StreamConfiguration, except that the streams
+ * vector contains @3.8::Stream.
+ */
+struct StreamConfiguration {
+    /**
+     * An array of camera stream pointers, defining the input/output
+     * configuration for the camera HAL device.
+     */
+    vec<Stream> streams;
+
+    /**
+     * The definition of operation mode from prior version.
+     *
+     */
+    @3.2::StreamConfigurationMode operationMode;
+
+    /**
+     * The definition of session parameters from prior version.
+     */
+    @3.2::CameraMetadata sessionParams;
+
+    /**
+     * The definition of stream configuration counter from prior version.
+     */
+    uint32_t streamConfigCounter;
+
+    /**
+     * If an input stream is configured, whether the input stream is expected to
+     * receive variable resolution images.
+     *
+     * This flag can only be set to true if the camera device supports
+     * multi-resolution input streams by advertising input stream configurations in
+     * physicalCameraMultiResolutionStreamConfigurations in its physical cameras'
+     * characteristics.
+     *
+     * When this flag is set to true, the input stream's width and height can be
+     * any one of the supported multi-resolution input stream sizes.
+     */
+    bool multiResolutionInputImage;
+};
+
diff --git a/camera/metadata/3.8/types.hal b/camera/metadata/3.8/types.hal
index 11360da..4c70eb9 100644
--- a/camera/metadata/3.8/types.hal
+++ b/camera/metadata/3.8/types.hal
@@ -53,6 +53,21 @@
 
     ANDROID_FLASH_INFO_END_3_8,
 
+    /** android.request.availableDynamicRangeProfilesMap [static, enum[], ndk_public]
+     *
+     * <p>A map of all available 10-bit dynamic range profiles along with their
+     * capture request constraints.</p>
+     */
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_REQUEST_END_3_4,
+
+    /** android.request.recommendedTenBitDynamicRangeProfile [static, int32, java_public]
+     *
+     * <p>Recommended 10-bit dynamic range profile.</p>
+     */
+    ANDROID_REQUEST_RECOMMENDED_TEN_BIT_DYNAMIC_RANGE_PROFILE,
+
+    ANDROID_REQUEST_END_3_8,
+
 };
 
 /*
@@ -66,3 +81,51 @@
         @3.2::CameraMetadataEnumAndroidControlVideoStabilizationMode {
     ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION,
 };
+
+/** android.request.availableCapabilities enumeration values added since v3.6
+ * @see ANDROID_REQUEST_AVAILABLE_CAPABILITIES
+ */
+enum CameraMetadataEnumAndroidRequestAvailableCapabilities :
+        @3.6::CameraMetadataEnumAndroidRequestAvailableCapabilities {
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT,
+};
+
+/** android.request.availableDynamicRangeProfilesMap enumeration values
+ * @see ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP
+ */
+enum CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap : uint32_t {
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD
+                                                                 = 0x1,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10  = 0x2,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10  = 0x4,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS
+                                                                 = 0x8,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF
+                                                                 = 0x10,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO
+                                                                 = 0x20,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM
+                                                                 = 0x40,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO
+                                                                 = 0x80,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF
+                                                                 = 0x100,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO
+                                                                 = 0x200,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM
+                                                                 = 0x400,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO
+                                                                 = 0x800,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_MAX    = 0x1000,
+};
+
+/** android.scaler.availableRecommendedStreamConfigurations enumeration values added since v3.4
+ * @see ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS
+ */
+enum CameraMetadataEnumAndroidScalerAvailableRecommendedStreamConfigurations :
+        @3.4::CameraMetadataEnumAndroidScalerAvailableRecommendedStreamConfigurations {
+    ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_10BIT_OUTPUT
+                                                                 = 0x8,
+    ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END_3_8
+                                                                 = 0x9,
+};
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 2c141ee..0e62265 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -51,11 +51,15 @@
         "android.hardware.camera.device@3.7",
         "android.hardware.camera.device@3.8",
         "android.hardware.camera.metadata@3.4",
+        "android.hardware.camera.metadata@3.8",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.provider@2.5",
         "android.hardware.camera.provider@2.6",
         "android.hardware.camera.provider@2.7",
         "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
         "android.hidl.allocator@1.0",
         "libgrallocusage",
         "libhidlmemory",
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index d39850d..8c44010 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -30,6 +30,7 @@
 
 #include <CameraMetadata.h>
 #include <CameraParameters.h>
+#include <HandleImporter.h>
 #include <android/hardware/camera/device/1.0/ICameraDevice.h>
 #include <android/hardware/camera/device/3.2/ICameraDevice.h>
 #include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
@@ -45,7 +46,9 @@
 #include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
 #include <android/hardware/camera/device/3.8/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.8/ICameraDeviceSession.h>
 #include <android/hardware/camera/metadata/3.4/types.h>
+#include <android/hardware/camera/metadata/3.8/types.h>
 #include <android/hardware/camera/provider/2.4/ICameraProvider.h>
 #include <android/hardware/camera/provider/2.5/ICameraProvider.h>
 #include <android/hardware/camera/provider/2.6/ICameraProvider.h>
@@ -97,6 +100,7 @@
 using ::android::hardware::camera::common::V1_0::TorchMode;
 using ::android::hardware::camera::common::V1_0::TorchModeStatus;
 using ::android::hardware::camera::common::V1_0::helper::CameraParameters;
+using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
 using ::android::hardware::camera::common::V1_0::helper::Size;
 using ::android::hardware::camera::device::V1_0::CameraFacing;
 using ::android::hardware::camera::device::V1_0::CameraFrameMetadata;
@@ -129,6 +133,8 @@
         CameraMetadataEnumAndroidSensorInfoColorFilterArrangement;
 using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag;
 using ::android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
+using ::android::hardware::camera::metadata::V3_8::
+        CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
 using ::android::hardware::camera::provider::V2_4::ICameraProvider;
 using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
 using ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination;
@@ -136,7 +142,6 @@
 using ::android::hardware::graphics::common::V1_0::Dataspace;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
 using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMapper;
 using ::android::hidl::memory::V1_0::IMemory;
 using ResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 using ::android::hidl::manager::V1_0::IServiceManager;
@@ -781,13 +786,15 @@
             sp<device::V3_4::ICameraDeviceSession> *session3_4 /*out*/,
             sp<device::V3_5::ICameraDeviceSession> *session3_5 /*out*/,
             sp<device::V3_6::ICameraDeviceSession> *session3_6 /*out*/,
-            sp<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/);
+            sp<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/,
+            sp<device::V3_8::ICameraDeviceSession> *session3_8 /*out*/);
     void castInjectionSession(
             const sp<ICameraDeviceSession>& session,
             sp<device::V3_7::ICameraInjectionSession>* injectionSession3_7 /*out*/);
     void castDevice(const sp<device::V3_2::ICameraDevice>& device, int32_t deviceVersion,
                     sp<device::V3_5::ICameraDevice>* device3_5 /*out*/,
-                    sp<device::V3_7::ICameraDevice>* device3_7 /*out*/);
+                    sp<device::V3_7::ICameraDevice>* device3_7 /*out*/,
+                    sp<device::V3_8::ICameraDevice>* device3_8 /*out*/);
     void createStreamConfiguration(
             const ::android::hardware::hidl_vec<V3_2::Stream>& streams3_2,
             StreamConfigurationMode configMode,
@@ -817,6 +824,16 @@
                              uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/,
                              sp<DeviceCb>* outCb /*out*/, uint32_t streamConfigCounter,
                              bool maxResolution);
+    void configureStreams3_8(const std::string& name, int32_t deviceVersion,
+                             sp<ICameraProvider> provider, PixelFormat format,
+                             sp<device::V3_8::ICameraDeviceSession>* session3_8 /*out*/,
+                             V3_2::Stream* previewStream /*out*/,
+                             device::V3_6::HalStreamConfiguration* halStreamConfig /*out*/,
+                             bool* supportsPartialResults /*out*/,
+                             uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/,
+                             sp<DeviceCb>* outCb /*out*/, uint32_t streamConfigCounter,
+                             bool maxResolution,
+                             CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap prof);
 
     void configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
             sp<ICameraProvider> provider,
@@ -896,6 +913,9 @@
     static bool isDepthOnly(const camera_metadata_t* staticMeta);
 
     static bool isUltraHighResolution(const camera_metadata_t* staticMeta);
+    static void get10BitDynamicRangeProfiles(const camera_metadata_t* staticMeta,
+        std::vector<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap> *profiles);
+    static bool is10BitDynamicRangeCapable(const camera_metadata_t* staticMeta);
 
     static Status getAvailableOutputStreams(const camera_metadata_t* staticMeta,
                                             std::vector<AvailableStream>& outputStreams,
@@ -949,7 +969,6 @@
     void getPrivacyTestPatternModes(
             const camera_metadata_t* staticMetadata,
             std::unordered_set<int32_t>* privacyTestPatternModes/*out*/);
-    static bool isColorCamera(const camera_metadata_t *metadata);
 
     static V3_2::DataspaceFlags getDataspace(PixelFormat format);
 
@@ -1077,6 +1096,10 @@
                 expectedPhysicalResults(extraPhysicalResult) {}
     };
 
+    static void verify10BitMetadata(HandleImporter& importer,
+            const InFlightRequest& request,
+            CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap profile);
+
     // Map from frame number to the in-flight request state
     typedef ::android::KeyedVector<uint32_t, InFlightRequest*> InFlightMap;
 
@@ -1105,6 +1128,8 @@
 
     // Camera provider type.
     std::string mProviderType;
+
+    HandleImporter mHandleImporter;
 };
 
 Return<void> CameraHidlTest::Camera1DeviceCb::notifyCallback(
@@ -3342,10 +3367,13 @@
                 sp<device::V3_5::ICameraDeviceSession> sessionV3_5;
                 sp<device::V3_6::ICameraDeviceSession> sessionV3_6;
                 sp<device::V3_7::ICameraDeviceSession> sessionV3_7;
+                sp<device::V3_8::ICameraDeviceSession> sessionV3_8;
                 castSession(session, deviceVersion, &sessionV3_3,
                         &sessionV3_4, &sessionV3_5, &sessionV3_6,
-                        &sessionV3_7);
-                if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_7) {
+                        &sessionV3_7, &sessionV3_8);
+                if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_8) {
+                    ASSERT_TRUE(sessionV3_8.get() != nullptr);
+                } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_7) {
                     ASSERT_TRUE(sessionV3_7.get() != nullptr);
                 } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_6) {
                     ASSERT_TRUE(sessionV3_6.get() != nullptr);
@@ -3513,14 +3541,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider,
                 &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         outputStreams.clear();
         ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
@@ -3616,9 +3647,11 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7;
         ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5;
         ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
@@ -3655,8 +3688,9 @@
             openEmptyDeviceSession(name, mProvider2_6, &cti.session /*out*/,
                                    &cti.staticMeta /*out*/, &cti.cameraDevice /*out*/);
             castSession(cti.session, deviceVersion, &cti.session3_3, &cti.session3_4,
-                        &cti.session3_5, &cti.session3_6, &cti.session3_7);
-            castDevice(cti.cameraDevice, deviceVersion, &cti.cameraDevice3_5, &cti.cameraDevice3_7);
+                        &cti.session3_5, &cti.session3_6, &cti.session3_7, &cti.session3_8);
+            castDevice(cti.cameraDevice, deviceVersion, &cti.cameraDevice3_5, &cti.cameraDevice3_7,
+                    &cti.cameraDevice3_8);
 
             outputStreams.clear();
             ASSERT_EQ(Status::OK, getMandatoryConcurrentStreams(cti.staticMeta, &outputStreams));
@@ -3785,14 +3819,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
                 &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         outputStreams.clear();
         ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
@@ -3998,14 +4035,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
                 &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         Status rc = isZSLModeAvailable(staticMeta);
         if (Status::METHOD_NOT_SUPPORTED == rc) {
@@ -4184,9 +4224,10 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMetaBuffer /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
+                &session3_6, &session3_7, &session3_8);
         if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_4) {
             ASSERT_NE(session3_4, nullptr);
         } else {
@@ -4325,14 +4366,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
                 &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         // Check if camera support depth only
         if (isDepthOnly(staticMeta)) {
@@ -4459,14 +4503,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
                 &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         Status rc = isConstrainedModeAvailable(staticMeta);
         if (Status::METHOD_NOT_SUPPORTED == rc) {
@@ -4706,14 +4753,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
                 &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         // Check if camera support depth only
         if (isDepthOnly(staticMeta)) {
@@ -4997,6 +5047,20 @@
         ASSERT_EQ(Status::OK, status);
         ASSERT_EQ(numRequestProcessed, 1u);
 
+        if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_8) {
+            sp<device::V3_3::ICameraDeviceSession> session3_3;
+            sp<device::V3_4::ICameraDeviceSession> session3_4;
+            sp<device::V3_5::ICameraDeviceSession> session3_5;
+            sp<device::V3_6::ICameraDeviceSession> session3_6;
+            sp<device::V3_7::ICameraDeviceSession> session3_7;
+            sp<device::V3_8::ICameraDeviceSession> session3_8;
+            castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
+                    &session3_6, &session3_7, &session3_8);
+            ASSERT_TRUE(session3_8.get() != nullptr);
+            hidl_vec<int32_t> streamIds = { halStreamConfig.streams[0].id };
+            session3_8->repeatingRequestEnd(request.frameNumber, streamIds);
+        }
+
         {
             std::unique_lock<std::mutex> l(mLock);
             while (!inflightReq.errorCodeValid &&
@@ -5640,6 +5704,188 @@
     }
 }
 
+// Generate and verify 10-bit dynamic range request
+TEST_P(CameraHidlTest, process10BitDynamicRangeRequest) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    uint64_t bufferId = 1;
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_8) {
+            continue;
+        }
+        std::string version, deviceId;
+        ASSERT_TRUE(::matchDeviceName(name, mProviderType, &version, &deviceId));
+        camera_metadata_t* staticMeta;
+        Return<void> ret;
+        sp<ICameraDeviceSession> session;
+        openEmptyDeviceSession(name, mProvider, &session, &staticMeta);
+        if (!is10BitDynamicRangeCapable(staticMeta)) {
+            free_camera_metadata(staticMeta);
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
+            continue;
+        }
+        std::vector<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap> profileList;
+        get10BitDynamicRangeProfiles(staticMeta, &profileList);
+        ASSERT_FALSE(profileList.empty());
+
+        android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
+        ret = session->constructDefaultRequestSettings(
+                RequestTemplate::STILL_CAPTURE,
+                [&defaultSettings](auto status, const auto& req) mutable {
+                    ASSERT_EQ(Status::OK, status);
+
+                    const camera_metadata_t* metadata =
+                            reinterpret_cast<const camera_metadata_t*>(req.data());
+                    size_t expectedSize = req.size();
+                    int result = validate_camera_metadata_structure(metadata, &expectedSize);
+                    ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
+
+                    size_t entryCount = get_camera_metadata_entry_count(metadata);
+                    ASSERT_GT(entryCount, 0u);
+                    defaultSettings = metadata;
+                });
+        ASSERT_TRUE(ret.isOk());
+
+        const camera_metadata_t* settingsBuffer = defaultSettings.getAndLock();
+        settings.setToExternal(
+                reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(settingsBuffer)),
+                get_camera_metadata_size(settingsBuffer));
+        overrideRotateAndCrop(&settings);
+
+        free_camera_metadata(staticMeta);
+        ret = session->close();
+        ASSERT_TRUE(ret.isOk());
+        V3_6::HalStreamConfiguration halStreamConfig;
+        bool supportsPartialResults = false;
+        bool useHalBufManager = false;
+        uint32_t partialResultCount = 0;
+        V3_2::Stream previewStream;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
+        sp<DeviceCb> cb;
+        for (const auto& profile : profileList) {
+            configureStreams3_8(name, deviceVersion, mProvider, PixelFormat::IMPLEMENTATION_DEFINED,
+                                &session3_8, &previewStream, &halStreamConfig,
+                                &supportsPartialResults, &partialResultCount, &useHalBufManager,
+                                &cb, 0, /*maxResolution*/ false, profile);
+            ASSERT_NE(session3_8, nullptr);
+
+            std::shared_ptr<ResultMetadataQueue> resultQueue;
+            auto resultQueueRet = session3_8->getCaptureResultMetadataQueue(
+                    [&resultQueue](const auto& descriptor) {
+                        resultQueue = std::make_shared<ResultMetadataQueue>(descriptor);
+                        if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
+                            ALOGE("%s: HAL returns empty result metadata fmq,"
+                                  " not use it",
+                                  __func__);
+                            resultQueue = nullptr;
+                            // Don't use the queue onwards.
+                        }
+                    });
+            ASSERT_TRUE(resultQueueRet.isOk());
+
+            std::vector<hidl_handle> graphicBuffers;
+            graphicBuffers.reserve(halStreamConfig.streams.size());
+            ::android::hardware::hidl_vec<StreamBuffer> outputBuffers;
+            outputBuffers.resize(halStreamConfig.streams.size());
+            InFlightRequest inflightReq = {static_cast<ssize_t>(halStreamConfig.streams.size()),
+                                           false,
+                                           supportsPartialResults,
+                                           partialResultCount,
+                                           std::unordered_set<std::string>(),
+                                           resultQueue};
+
+            size_t k = 0;
+            for (const auto& halStream : halStreamConfig.streams) {
+                hidl_handle buffer_handle;
+                if (useHalBufManager) {
+                    outputBuffers[k] = {halStream.v3_4.v3_3.v3_2.id,
+                                        0,
+                                        buffer_handle,
+                                        BufferStatus::OK,
+                                        nullptr,
+                                        nullptr};
+                } else {
+                    allocateGraphicBuffer(
+                            previewStream.width, previewStream.height,
+                            android_convertGralloc1To0Usage(halStream.v3_4.v3_3.v3_2.producerUsage,
+                                                            halStream.v3_4.v3_3.v3_2.consumerUsage),
+                            halStream.v3_4.v3_3.v3_2.overrideFormat, &buffer_handle);
+
+                    graphicBuffers.push_back(buffer_handle);
+                    outputBuffers[k] = {halStream.v3_4.v3_3.v3_2.id,
+                                        bufferId,
+                                        buffer_handle,
+                                        BufferStatus::OK,
+                                        nullptr,
+                                        nullptr};
+                    bufferId++;
+                }
+                k++;
+            }
+
+            StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
+            V3_4::CaptureRequest request3_4;
+            request3_4.v3_2.frameNumber = frameNumber;
+            request3_4.v3_2.fmqSettingsSize = 0;
+            request3_4.v3_2.settings = settings;
+            request3_4.v3_2.inputBuffer = emptyInputBuffer;
+            request3_4.v3_2.outputBuffers = outputBuffers;
+            V3_7::CaptureRequest request3_7;
+            request3_7.v3_4 = request3_4;
+            request3_7.inputWidth = 0;
+            request3_7.inputHeight = 0;
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                mInflightMap.clear();
+                mInflightMap.add(frameNumber, &inflightReq);
+            }
+
+            Status stat = Status::INTERNAL_ERROR;
+            uint32_t numRequestProcessed = 0;
+            hidl_vec<BufferCache> cachesToRemove;
+            Return<void> returnStatus = session3_8->processCaptureRequest_3_7(
+                    {request3_7}, cachesToRemove,
+                    [&stat, &numRequestProcessed](auto s, uint32_t n) {
+                        stat = s;
+                        numRequestProcessed = n;
+                    });
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, stat);
+            ASSERT_EQ(numRequestProcessed, 1u);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                while (!inflightReq.errorCodeValid &&
+                       ((0 < inflightReq.numBuffersLeft) || (!inflightReq.haveResultMetadata))) {
+                    auto timeout = std::chrono::system_clock::now() +
+                                   std::chrono::seconds(kStreamBufferTimeoutSec);
+                    ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
+                }
+
+                ASSERT_FALSE(inflightReq.errorCodeValid);
+                ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
+                verify10BitMetadata(mHandleImporter, inflightReq, profile);
+            }
+            if (useHalBufManager) {
+                hidl_vec<int32_t> streamIds(halStreamConfig.streams.size());
+                for (size_t i = 0; i < streamIds.size(); i++) {
+                    streamIds[i] = halStreamConfig.streams[i].v3_4.v3_3.v3_2.id;
+                }
+                session3_8->signalStreamFlush(streamIds, /*streamConfigCounter*/ 0);
+                cb->waitForBuffersReturned();
+            }
+
+            ret = session3_8->close();
+            ASSERT_TRUE(ret.isOk());
+        }
+    }
+}
+
 // Generate and verify a burst containing alternating sensor sensitivity values
 TEST_P(CameraHidlTest, processCaptureRequestBurstISO) {
     hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
@@ -6633,142 +6879,6 @@
     }
 }
 
-// Test the multi-camera API requirement for Google Requirement Freeze S
-// Note that this requirement can only be partially tested. If a vendor
-// device doesn't expose a physical camera in any shape or form, there is no way
-// the test can catch it.
-TEST_P(CameraHidlTest, grfSMultiCameraTest) {
-    const int socGrfApi = property_get_int32("ro.board.first_api_level", /*default*/ -1);
-    if (socGrfApi < 31 /*S*/) {
-        // Non-GRF devices, or version < 31 Skip
-        ALOGI("%s: socGrfApi level is %d. Skipping", __FUNCTION__, socGrfApi);
-        return;
-    }
-
-    // Test that if more than one rear-facing color camera is
-    // supported, there must be at least one rear-facing logical camera.
-    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
-    // Back facing non-logical color cameras
-    std::set<std::string> rearColorCameras;
-    // Back facing logical cameras' physical camera Id sets
-    std::set<std::set<std::string>> rearPhysicalIds;
-    for (const auto& name : cameraDeviceNames) {
-        std::string cameraId;
-        int deviceVersion = getCameraDeviceVersionAndId(name, mProviderType, &cameraId);
-        switch (deviceVersion) {
-            case CAMERA_DEVICE_API_VERSION_3_8:
-            case CAMERA_DEVICE_API_VERSION_3_7:
-            case CAMERA_DEVICE_API_VERSION_3_6:
-            case CAMERA_DEVICE_API_VERSION_3_5:
-            case CAMERA_DEVICE_API_VERSION_3_4:
-            case CAMERA_DEVICE_API_VERSION_3_3:
-            case CAMERA_DEVICE_API_VERSION_3_2: {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
-                ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
-                Return<void> ret;
-                ret = mProvider->getCameraDeviceInterface_V3_x(
-                        name, [&](auto status, const auto& device) {
-                            ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
-                            ASSERT_EQ(Status::OK, status);
-                            ASSERT_NE(device, nullptr);
-                            device3_x = device;
-                        });
-                ASSERT_TRUE(ret.isOk());
-
-                ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) {
-                    ASSERT_EQ(Status::OK, status);
-                    const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
-
-                    // Skip if this is not a color camera.
-                    if (!CameraHidlTest::isColorCamera(metadata)) {
-                        return;
-                    }
-
-                    // Check camera facing. Skip if facing is not BACK.
-                    // If this is not a logical camera, only note down
-                    // the camera ID, and skip.
-                    camera_metadata_ro_entry entry;
-                    int retcode = find_camera_metadata_ro_entry(
-                            metadata, ANDROID_LENS_FACING, &entry);
-                    ASSERT_EQ(retcode, 0);
-                    ASSERT_GT(entry.count, 0);
-                    uint8_t facing = entry.data.u8[0];
-                    bool isLogicalCamera = (isLogicalMultiCamera(metadata) == Status::OK);
-                    if (facing != ANDROID_LENS_FACING_BACK) {
-                        // Not BACK facing. Skip.
-                        return;
-                    }
-                    if (!isLogicalCamera) {
-                        rearColorCameras.insert(cameraId);
-                        return;
-                    }
-
-                    // Check logical camera's physical camera IDs for color
-                    // cameras.
-                    std::unordered_set<std::string> physicalCameraIds;
-                    Status s = getPhysicalCameraIds(metadata, &physicalCameraIds);
-                    ASSERT_EQ(Status::OK, s);
-                    rearPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end());
-                    for (const auto& physicalId : physicalCameraIds) {
-                        // Skip if the physicalId is publicly available
-                        for (auto& deviceName : cameraDeviceNames) {
-                            std::string publicVersion, publicId;
-                            ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType,
-                                                          &publicVersion, &publicId));
-                            if (physicalId == publicId) {
-                                // Skip because public Ids will be iterated in outer loop.
-                                return;
-                            }
-                        }
-
-                        auto castResult = device::V3_5::ICameraDevice::castFrom(device3_x);
-                        ASSERT_TRUE(castResult.isOk());
-                        ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice>
-                                device3_5 = castResult;
-                        ASSERT_NE(device3_5, nullptr);
-
-                        // Check camera characteristics for hidden camera id
-                        Return<void> ret = device3_5->getPhysicalCameraCharacteristics(
-                                physicalId, [&](auto status, const auto& chars) {
-                            ASSERT_EQ(Status::OK, status);
-                            const camera_metadata_t* physicalMetadata =
-                                    (camera_metadata_t*)chars.data();
-
-                            if (CameraHidlTest::isColorCamera(physicalMetadata)) {
-                                rearColorCameras.insert(physicalId);
-                            }
-                        });
-                        ASSERT_TRUE(ret.isOk());
-                    }
-                });
-                ASSERT_TRUE(ret.isOk());
-            } break;
-            case CAMERA_DEVICE_API_VERSION_1_0: {
-                // Not applicable
-            } break;
-            default: {
-                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
-                ADD_FAILURE();
-            } break;
-        }
-    }
-
-    // If there are more than one rear-facing color camera, a logical
-    // multi-camera must be defined consisting of all rear-facing color
-    // cameras.
-    if (rearColorCameras.size() > 1) {
-        bool hasRearLogical = false;
-        for (const auto& physicalIds : rearPhysicalIds) {
-            if (std::includes(physicalIds.begin(), physicalIds.end(),
-                    rearColorCameras.begin(), rearColorCameras.end())) {
-                hasRearLogical = true;
-                break;
-            }
-        }
-        ASSERT_TRUE(hasRearLogical);
-    }
-}
-
 // Retrieve all valid output stream resolutions from the camera
 // static characteristics.
 Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
@@ -7276,23 +7386,6 @@
     return ret;
 }
 
-bool CameraHidlTest::isColorCamera(const camera_metadata_t *metadata) {
-    camera_metadata_ro_entry entry;
-    int retcode = find_camera_metadata_ro_entry(
-            metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
-    if ((0 == retcode) && (entry.count > 0)) {
-        bool isBackwardCompatible = (std::find(entry.data.u8, entry.data.u8 + entry.count,
-                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) !=
-                entry.data.u8 + entry.count);
-        bool isMonochrome = (std::find(entry.data.u8, entry.data.u8 + entry.count,
-                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) !=
-                entry.data.u8 + entry.count);
-        bool isColor = isBackwardCompatible && !isMonochrome;
-        return isColor;
-    }
-    return false;
-}
-
 // Retrieve the reprocess input-output format map from the static
 // camera characteristics.
 Status CameraHidlTest::getZSLInputOutputMap(camera_metadata_t *staticMeta,
@@ -7448,8 +7541,9 @@
     sp<device::V3_4::ICameraDeviceSession> session3_4;
     sp<device::V3_5::ICameraDeviceSession> session3_5;
     sp<device::V3_6::ICameraDeviceSession> session3_6;
+    sp<device::V3_8::ICameraDeviceSession> session3_8;
     castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6,
-                session3_7);
+                session3_7, &session3_8);
     ASSERT_NE(nullptr, (*session3_7).get());
 
     *useHalBufManager = false;
@@ -7497,7 +7591,8 @@
     ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_7);
     sp<device::V3_5::ICameraDevice> cameraDevice3_5 = nullptr;
     sp<device::V3_7::ICameraDevice> cameraDevice3_7 = nullptr;
-    castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+    sp<device::V3_8::ICameraDevice> cameraDevice3_8 = nullptr;
+    castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7, &cameraDevice3_8);
     ASSERT_NE(cameraDevice3_7, nullptr);
     bool supported = false;
     ret = cameraDevice3_7->isStreamCombinationSupported_3_7(
@@ -7530,6 +7625,153 @@
     ASSERT_TRUE(ret.isOk());
 }
 
+// Configure streams
+void CameraHidlTest::configureStreams3_8(
+        const std::string& name, int32_t deviceVersion, sp<ICameraProvider> provider,
+        PixelFormat format, sp<device::V3_8::ICameraDeviceSession>* session3_8 /*out*/,
+        V3_2::Stream* previewStream /*out*/,
+        device::V3_6::HalStreamConfiguration* halStreamConfig /*out*/,
+        bool* supportsPartialResults /*out*/, uint32_t* partialResultCount /*out*/,
+        bool* useHalBufManager /*out*/, sp<DeviceCb>* outCb /*out*/, uint32_t streamConfigCounter,
+        bool maxResolution,
+        CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap prof) {
+    ASSERT_NE(nullptr, session3_8);
+    ASSERT_NE(nullptr, halStreamConfig);
+    ASSERT_NE(nullptr, previewStream);
+    ASSERT_NE(nullptr, supportsPartialResults);
+    ASSERT_NE(nullptr, partialResultCount);
+    ASSERT_NE(nullptr, useHalBufManager);
+    ASSERT_NE(nullptr, outCb);
+    ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_8);
+
+    std::vector<AvailableStream> outputStreams;
+    ::android::sp<ICameraDevice> device3_x;
+    ALOGI("configureStreams: Testing camera device %s", name.c_str());
+    Return<void> ret;
+    ret = provider->getCameraDeviceInterface_V3_x(name, [&](auto status, const auto& device) {
+        ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+        ASSERT_EQ(Status::OK, status);
+        ASSERT_NE(device, nullptr);
+        device3_x = device;
+    });
+    ASSERT_TRUE(ret.isOk());
+
+    camera_metadata_t* staticMeta;
+    ret = device3_x->getCameraCharacteristics([&](Status s, CameraMetadata metadata) {
+        ASSERT_EQ(Status::OK, s);
+        staticMeta =
+                clone_camera_metadata(reinterpret_cast<const camera_metadata_t*>(metadata.data()));
+        ASSERT_NE(nullptr, staticMeta);
+    });
+    ASSERT_TRUE(ret.isOk());
+
+    camera_metadata_ro_entry entry;
+    auto status =
+            find_camera_metadata_ro_entry(staticMeta, ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &entry);
+    if ((0 == status) && (entry.count > 0)) {
+        *partialResultCount = entry.data.i32[0];
+        *supportsPartialResults = (*partialResultCount > 1);
+    }
+
+    sp<DeviceCb> cb = new DeviceCb(this, deviceVersion, staticMeta);
+    sp<ICameraDeviceSession> session;
+    ret = device3_x->open(cb, [&session](auto status, const auto& newSession) {
+        ALOGI("device::open returns status:%d", (int)status);
+        ASSERT_EQ(Status::OK, status);
+        ASSERT_NE(newSession, nullptr);
+        session = newSession;
+    });
+    ASSERT_TRUE(ret.isOk());
+    *outCb = cb;
+
+    sp<device::V3_3::ICameraDeviceSession> session3_3;
+    sp<device::V3_4::ICameraDeviceSession> session3_4;
+    sp<device::V3_5::ICameraDeviceSession> session3_5;
+    sp<device::V3_6::ICameraDeviceSession> session3_6;
+    sp<device::V3_7::ICameraDeviceSession> session3_7;
+    castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6,
+                &session3_7, session3_8);
+    ASSERT_NE(nullptr, (*session3_8).get());
+
+    *useHalBufManager = false;
+    status = find_camera_metadata_ro_entry(
+            staticMeta, ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &entry);
+    if ((0 == status) && (entry.count == 1)) {
+        *useHalBufManager = (entry.data.u8[0] ==
+                             ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+    }
+
+    outputStreams.clear();
+    Size maxSize;
+    auto rc = getMaxOutputSizeForFormat(staticMeta, format, &maxSize, maxResolution);
+    ASSERT_EQ(Status::OK, rc);
+    free_camera_metadata(staticMeta);
+
+    ::android::hardware::hidl_vec<V3_8::Stream> streams3_8(1);
+    streams3_8[0].v3_7.groupId = -1;
+    streams3_8[0].v3_7.sensorPixelModesUsed = {
+            CameraMetadataEnumAndroidSensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT};
+    streams3_8[0].v3_7.v3_4.bufferSize = 0;
+    streams3_8[0].v3_7.v3_4.v3_2.id = 0;
+    streams3_8[0].v3_7.v3_4.v3_2.streamType = StreamType::OUTPUT;
+    streams3_8[0].v3_7.v3_4.v3_2.width = static_cast<uint32_t>(maxSize.width);
+    streams3_8[0].v3_7.v3_4.v3_2.height = static_cast<uint32_t>(maxSize.height);
+    streams3_8[0].v3_7.v3_4.v3_2.format = static_cast<PixelFormat>(format);
+    streams3_8[0].v3_7.v3_4.v3_2.usage = GRALLOC1_CONSUMER_USAGE_CPU_READ;
+    streams3_8[0].v3_7.v3_4.v3_2.dataSpace = 0;
+    streams3_8[0].v3_7.v3_4.v3_2.rotation = StreamRotation::ROTATION_0;
+    streams3_8[0].dynamicRangeProfile = prof;
+
+    ::android::hardware::camera::device::V3_8::StreamConfiguration config3_8;
+    config3_8.streams = streams3_8;
+    config3_8.operationMode = StreamConfigurationMode::NORMAL_MODE;
+    config3_8.streamConfigCounter = streamConfigCounter;
+    config3_8.multiResolutionInputImage = false;
+    RequestTemplate reqTemplate = RequestTemplate::STILL_CAPTURE;
+    ret = (*session3_8)
+                  ->constructDefaultRequestSettings(reqTemplate,
+                                                    [&config3_8](auto status, const auto& req) {
+                                                        ASSERT_EQ(Status::OK, status);
+                                                        config3_8.sessionParams = req;
+                                                    });
+    ASSERT_TRUE(ret.isOk());
+
+    sp<device::V3_5::ICameraDevice> cameraDevice3_5 = nullptr;
+    sp<device::V3_7::ICameraDevice> cameraDevice3_7 = nullptr;
+    sp<device::V3_8::ICameraDevice> cameraDevice3_8 = nullptr;
+    castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7, &cameraDevice3_8);
+    ASSERT_NE(cameraDevice3_8, nullptr);
+    bool supported = false;
+    ret = cameraDevice3_8->isStreamCombinationSupported_3_8(
+            config3_8, [&supported](Status s, bool combStatus) {
+                ASSERT_TRUE((Status::OK == s) || (Status::METHOD_NOT_SUPPORTED == s));
+                if (Status::OK == s) {
+                    supported = combStatus;
+                }
+            });
+    ASSERT_TRUE(ret.isOk());
+    ASSERT_EQ(supported, true);
+
+    if (*session3_8 != nullptr) {
+        ret = (*session3_8)
+                      ->configureStreams_3_8(
+                              config3_8,
+                              [&](Status s, device::V3_6::HalStreamConfiguration halConfig) {
+                                  ASSERT_EQ(Status::OK, s);
+                                  *halStreamConfig = halConfig;
+                                  if (*useHalBufManager) {
+                                      hidl_vec<V3_4::Stream> streams(1);
+                                      hidl_vec<V3_2::HalStream> halStreams(1);
+                                      streams[0] = streams3_8[0].v3_7.v3_4;
+                                      halStreams[0] = halConfig.streams[0].v3_4.v3_3.v3_2;
+                                      cb->setCurrentStreamConfig(streams, halStreams);
+                                  }
+                              });
+    }
+    *previewStream = streams3_8[0].v3_7.v3_4.v3_2;
+    ASSERT_TRUE(ret.isOk());
+}
+
 // Configure multiple preview streams using different physical ids.
 void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
         sp<ICameraProvider> provider,
@@ -7604,8 +7846,9 @@
     sp<device::V3_3::ICameraDeviceSession> session3_3;
     sp<device::V3_6::ICameraDeviceSession> session3_6;
     sp<device::V3_7::ICameraDeviceSession> session3_7;
+    sp<device::V3_8::ICameraDeviceSession> session3_8;
     castSession(session, deviceVersion, &session3_3, session3_4, session3_5,
-            &session3_6, &session3_7);
+            &session3_6, &session3_7, &session3_8);
     ASSERT_NE(nullptr, (*session3_4).get());
 
     *useHalBufManager = false;
@@ -7650,7 +7893,8 @@
     if (allowUnsupport) {
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
-        castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
+        castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7, &cameraDevice3_8);
 
         bool supported = false;
         ret = cameraDevice3_5->isStreamCombinationSupported(config3_4,
@@ -7843,6 +8087,95 @@
     return false;
 }
 
+void CameraHidlTest::get10BitDynamicRangeProfiles(const camera_metadata_t* staticMeta,
+        std::vector<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap> *profiles) {
+    ASSERT_NE(nullptr, staticMeta);
+    ASSERT_NE(nullptr, profiles);
+    camera_metadata_ro_entry entry;
+    std::unordered_set<int32_t> entries;
+    int rc = find_camera_metadata_ro_entry(staticMeta,
+            ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP, &entry);
+    ASSERT_EQ(rc, 0);
+    ASSERT_TRUE(entry.count > 0);
+    ASSERT_EQ(entry.count % 2, 0);
+
+    for (uint32_t i = 0; i < entry.count; i += 2) {
+        ASSERT_NE(entry.data.i32[i],
+                ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
+        ASSERT_EQ(entries.find(entry.data.i32[i]), entries.end());
+        entries.insert(static_cast<int32_t>(entry.data.i32[i]));
+        profiles->emplace_back(
+                static_cast<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap>
+                (entry.data.i32[i]));
+    }
+
+    if (!entries.empty()) {
+        ASSERT_NE(entries.find(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10),
+                entries.end());
+    }
+}
+
+bool CameraHidlTest::is10BitDynamicRangeCapable(const camera_metadata_t* staticMeta) {
+    camera_metadata_ro_entry scalarEntry;
+    int rc = find_camera_metadata_ro_entry(staticMeta, ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+                                           &scalarEntry);
+    if (rc == 0) {
+        for (uint32_t i = 0; i < scalarEntry.count; i++) {
+            if (scalarEntry.data.u8[i] ==
+                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+void CameraHidlTest::verify10BitMetadata(HandleImporter& importer,
+        const InFlightRequest& request,
+        CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap profile) {
+    for (const auto& b : request.resultOutputBuffers) {
+        bool smpte2086Present = importer.isSmpte2086Present(b.buffer.buffer.getNativeHandle());
+        bool smpte2094_10Present = importer.isSmpte2094_10Present(
+                b.buffer.buffer.getNativeHandle());
+        bool smpte2094_40Present = importer.isSmpte2094_40Present(
+                b.buffer.buffer.getNativeHandle());
+
+        switch (static_cast<uint32_t>(profile)) {
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
+                ASSERT_FALSE(smpte2086Present);
+                ASSERT_FALSE(smpte2094_10Present);
+                ASSERT_FALSE(smpte2094_40Present);
+                break;
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
+                ASSERT_TRUE(smpte2086Present);
+                ASSERT_FALSE(smpte2094_10Present);
+                ASSERT_FALSE(smpte2094_40Present);
+                break;
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
+                ASSERT_FALSE(smpte2086Present);
+                ASSERT_FALSE(smpte2094_10Present);
+                ASSERT_TRUE(smpte2094_40Present);
+                break;
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO:
+                ASSERT_FALSE(smpte2086Present);
+                ASSERT_TRUE(smpte2094_10Present);
+                ASSERT_FALSE(smpte2094_40Present);
+                break;
+            default:
+                ALOGE("%s: Unexpected 10-bit dynamic range profile: %d",
+                        __FUNCTION__, profile);
+                ADD_FAILURE();
+        }
+    }
+}
+
 bool CameraHidlTest::isDepthOnly(const camera_metadata_t* staticMeta) {
     camera_metadata_ro_entry scalarEntry;
     camera_metadata_ro_entry depthEntry;
@@ -8006,8 +8339,9 @@
     sp<device::V3_5::ICameraDeviceSession> session3_5;
     sp<device::V3_6::ICameraDeviceSession> session3_6;
     sp<device::V3_7::ICameraDeviceSession> session3_7;
+    sp<device::V3_8::ICameraDeviceSession> session3_8;
     castSession(*session, deviceVersion, &session3_3, &session3_4, &session3_5,
-            &session3_6, &session3_7);
+            &session3_6, &session3_7, &session3_8);
 
     *useHalBufManager = false;
     status = find_camera_metadata_ro_entry(staticMeta,
@@ -8138,12 +8472,19 @@
 void CameraHidlTest::castDevice(const sp<device::V3_2::ICameraDevice>& device,
                                 int32_t deviceVersion,
                                 sp<device::V3_5::ICameraDevice>* device3_5 /*out*/,
-                                sp<device::V3_7::ICameraDevice>* device3_7 /*out*/) {
+                                sp<device::V3_7::ICameraDevice>* device3_7 /*out*/,
+                                sp<device::V3_8::ICameraDevice>* device3_8 /*out*/) {
     ASSERT_NE(nullptr, device3_5);
     ASSERT_NE(nullptr, device3_7);
+    ASSERT_NE(nullptr, device3_8);
 
     switch (deviceVersion) {
-        case CAMERA_DEVICE_API_VERSION_3_8:
+        case CAMERA_DEVICE_API_VERSION_3_8: {
+            auto castResult = device::V3_8::ICameraDevice::castFrom(device);
+            ASSERT_TRUE(castResult.isOk());
+            *device3_8 = castResult;
+        }
+            [[fallthrough]];
         case CAMERA_DEVICE_API_VERSION_3_7: {
             auto castResult = device::V3_7::ICameraDevice::castFrom(device);
             ASSERT_TRUE(castResult.isOk());
@@ -8192,15 +8533,22 @@
         sp<device::V3_4::ICameraDeviceSession> *session3_4 /*out*/,
         sp<device::V3_5::ICameraDeviceSession> *session3_5 /*out*/,
         sp<device::V3_6::ICameraDeviceSession> *session3_6 /*out*/,
-        sp<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/) {
+        sp<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/,
+        sp<device::V3_8::ICameraDeviceSession> *session3_8 /*out*/) {
     ASSERT_NE(nullptr, session3_3);
     ASSERT_NE(nullptr, session3_4);
     ASSERT_NE(nullptr, session3_5);
     ASSERT_NE(nullptr, session3_6);
     ASSERT_NE(nullptr, session3_7);
+    ASSERT_NE(nullptr, session3_8);
 
     switch (deviceVersion) {
-        case CAMERA_DEVICE_API_VERSION_3_8:
+        case CAMERA_DEVICE_API_VERSION_3_8: {
+            auto castResult = device::V3_8::ICameraDeviceSession::castFrom(session);
+            ASSERT_TRUE(castResult.isOk());
+            *session3_8 = castResult;
+        }
+        [[fallthrough]];
         case CAMERA_DEVICE_API_VERSION_3_7: {
             auto castResult = device::V3_7::ICameraDeviceSession::castFrom(session);
             ASSERT_TRUE(castResult.isOk());
@@ -9077,8 +9425,9 @@
     sp<device::V3_5::ICameraDeviceSession> session3_5;
     sp<device::V3_6::ICameraDeviceSession> session3_6;
     sp<device::V3_7::ICameraDeviceSession> session3_7;
+    sp<device::V3_8::ICameraDeviceSession> session3_8;
     castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-            &session3_6, &session3_7);
+            &session3_6, &session3_7, &session3_8);
     ASSERT_NE(nullptr, session3_5.get());
 
     hidl_vec<int32_t> streamIds(1);
@@ -9320,7 +9669,7 @@
     size_t CONFIG_ENTRY_TYPE_OFFSET = 3;
     size_t CONFIG_ENTRY_BITFIELD_OFFSET = 4;
     uint32_t maxPublicUsecase =
-            ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END;
+            ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END_3_8;
     uint32_t vendorUsecaseStart =
             ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VENDOR_START;
     uint32_t usecaseMask = (1 << vendorUsecaseStart) - 1;
diff --git a/camera/provider/2.7/default/Android.bp b/camera/provider/2.7/default/Android.bp
new file mode 100644
index 0000000..bd5da2d
--- /dev/null
+++ b/camera/provider/2.7/default/Android.bp
@@ -0,0 +1,111 @@
+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.camera.provider@2.7-external",
+    proprietary: true,
+    srcs: ["ExternalCameraProviderImpl_2_7.cpp"],
+    shared_libs: [
+        "android.hardware.camera.common@1.0",
+        "android.hardware.camera.device@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.3",
+        "android.hardware.camera.device@3.4",
+        "android.hardware.camera.device@3.5",
+        "android.hardware.camera.device@3.6",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.camera.provider@2.5",
+        "android.hardware.camera.provider@2.6",
+        "android.hardware.camera.provider@2.7",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "camera.device@3.3-impl",
+        "camera.device@3.4-external-impl",
+        "camera.device@3.4-impl",
+        "camera.device@3.5-external-impl",
+        "camera.device@3.5-impl",
+        "camera.device@3.6-external-impl",
+        "libcamera_metadata",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "liblog",
+        "libtinyxml2",
+        "libutils",
+    ],
+    static_libs: [
+        "android.hardware.camera.common@1.0-helper",
+    ],
+    header_libs: [
+        "camera.device@3.4-external-impl_headers",
+        "camera.device@3.5-external-impl_headers",
+        "camera.device@3.6-external-impl_headers",
+    ],
+    export_include_dirs: ["."],
+}
+
+cc_defaults {
+    name: "camera_external_service_2_7_defaults",
+    defaults: ["hidl_defaults"],
+    proprietary: true,
+    relative_install_path: "hw",
+    srcs: ["external-service.cpp"],
+    compile_multilib: "32",
+    shared_libs: [
+        "android.hardware.camera.common@1.0",
+        "android.hardware.camera.device@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.3",
+        "android.hardware.camera.device@3.4",
+        "android.hardware.camera.device@3.5",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.camera.provider@2.4-external",
+        "android.hardware.camera.provider@2.5",
+        "android.hardware.camera.provider@2.5-external",
+        "android.hardware.camera.provider@2.6",
+        "android.hardware.camera.provider@2.7",
+        "android.hardware.camera.provider@2.7-external",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
+        "libbinder",
+        "libcamera_metadata",
+        "libhidlbase",
+        "liblog",
+        "libtinyxml2",
+        "libutils",
+    ],
+    static_libs: [
+        "android.hardware.camera.common@1.0-helper",
+    ],
+    header_libs: [
+        "camera.device@3.4-external-impl_headers",
+        "camera.device@3.4-impl_headers",
+        "camera.device@3.5-external-impl_headers",
+        "camera.device@3.5-impl_headers",
+        "camera.device@3.6-external-impl_headers",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.camera.provider@2.7-external-service",
+    defaults: ["camera_external_service_2_7_defaults"],
+    init_rc: ["android.hardware.camera.provider@2.7-external-service.rc"],
+}
+
+cc_binary {
+    name: "android.hardware.camera.provider@2.7-external-service-lazy",
+    overrides: ["android.hardware.camera.provider@2.7-external-service"],
+    defaults: ["camera_external_service_2_7_defaults"],
+    init_rc: ["android.hardware.camera.provider@2.7-external-service-lazy.rc"],
+    cflags: ["-DLAZY_SERVICE"],
+}
diff --git a/camera/provider/2.7/default/CameraProvider_2_7.h b/camera/provider/2.7/default/CameraProvider_2_7.h
new file mode 100644
index 0000000..c34905f
--- /dev/null
+++ b/camera/provider/2.7/default/CameraProvider_2_7.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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA_PROVIDER_V2_7_CAMERAPROVIDER_H
+#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_7_CAMERAPROVIDER_H
+
+#include <android/hardware/camera/provider/2.6/ICameraProviderCallback.h>
+#include <android/hardware/camera/provider/2.7/ICameraProvider.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace provider {
+namespace V2_7 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::TorchModeStatus;
+using ::android::hardware::camera::common::V1_0::VendorTag;
+using ::android::hardware::camera::common::V1_0::VendorTagSection;
+using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
+using ::android::hardware::camera::provider::V2_5::DeviceState;
+using ::android::hardware::camera::provider::V2_7::CameraIdAndStreamCombination;
+using ::android::hardware::camera::provider::V2_7::ICameraProvider;
+using ::android::hidl::base::V1_0::IBase;
+
+// Default recommended RPC thread count for camera provider implementations
+const int HWBINDER_THREAD_COUNT = 6;
+
+template <typename IMPL>
+struct CameraProvider : public ICameraProvider {
+    CameraProvider() : impl() {}
+    ~CameraProvider() {}
+
+    // Caller must use this method to check if CameraProvider ctor failed
+    bool isInitFailed() { return impl.isInitFailed(); }
+
+    // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow.
+    Return<Status> setCallback(const sp<ICameraProviderCallback>& callback) override {
+        return impl.setCallback(callback);
+    }
+
+    Return<void> getVendorTags(getVendorTags_cb _hidl_cb) override {
+        return impl.getVendorTags(_hidl_cb);
+    }
+
+    Return<void> getCameraIdList(getCameraIdList_cb _hidl_cb) override {
+        return impl.getCameraIdList(_hidl_cb);
+    }
+
+    Return<void> isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) override {
+        return impl.isSetTorchModeSupported(_hidl_cb);
+    }
+
+    Return<void> getCameraDeviceInterface_V1_x(const hidl_string& cameraDeviceName,
+                                               getCameraDeviceInterface_V1_x_cb _hidl_cb) override {
+        return impl.getCameraDeviceInterface_V1_x(cameraDeviceName, _hidl_cb);
+    }
+
+    Return<void> getCameraDeviceInterface_V3_x(const hidl_string& cameraDeviceName,
+                                               getCameraDeviceInterface_V3_x_cb _hidl_cb) override {
+        return impl.getCameraDeviceInterface_V3_x(cameraDeviceName, _hidl_cb);
+    }
+
+    // Methods from ::android::hardware::camera::provider::V2_5::ICameraProvider follow.
+    Return<void> notifyDeviceStateChange(hardware::hidl_bitfield<DeviceState> newState) override {
+        return impl.notifyDeviceStateChange(newState);
+    }
+
+    // Methods from ::android::hardware::camera::provider::V2_7::ICameraProvider follow.
+    Return<void> getConcurrentStreamingCameraIds(
+            getConcurrentStreamingCameraIds_cb _hidl_cb) override {
+        return impl.getConcurrentStreamingCameraIds(_hidl_cb);
+    }
+
+    Return<void> isConcurrentStreamCombinationSupported(
+            const hidl_vec<
+                    ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination>&
+                    configs,
+            isConcurrentStreamCombinationSupported_cb _hidl_cb) override {
+        return impl.isConcurrentStreamCombinationSupported(configs, _hidl_cb);
+    }
+
+    Return<void> isConcurrentStreamCombinationSupported_2_7(
+            const hidl_vec<CameraIdAndStreamCombination>& configs,
+            isConcurrentStreamCombinationSupported_2_7_cb _hidl_cb) override {
+        return impl.isConcurrentStreamCombinationSupported_2_7(configs, _hidl_cb);
+    }
+
+  private:
+    IMPL impl;
+};
+
+}  // namespace implementation
+}  // namespace V2_7
+}  // namespace provider
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H
\ No newline at end of file
diff --git a/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp
new file mode 100644
index 0000000..c812d54
--- /dev/null
+++ b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "CamPrvdr@2.7-external"
+//#define LOG_NDEBUG 0
+#include <log/log.h>
+
+#include <cutils/properties.h>
+#include <errno.h>
+#include <linux/videodev2.h>
+#include <sys/inotify.h>
+#include <regex>
+#include "ExternalCameraDevice_3_4.h"
+#include "ExternalCameraDevice_3_5.h"
+#include "ExternalCameraDevice_3_6.h"
+#include "ExternalCameraProviderImpl_2_7.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace provider {
+namespace V2_7 {
+namespace implementation {
+
+namespace {
+// "device@<version>/external/<id>"
+const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/external/(.+)");
+const int kMaxDevicePathLen = 256;
+const char* kDevicePath = "/dev/";
+constexpr char kPrefix[] = "video";
+constexpr int kPrefixLen = sizeof(kPrefix) - 1;
+constexpr int kDevicePrefixLen = sizeof(kDevicePath) + kPrefixLen + 1;
+
+bool matchDeviceName(int cameraIdOffset, const hidl_string& deviceName, std::string* deviceVersion,
+                     std::string* cameraDevicePath) {
+    std::string deviceNameStd(deviceName.c_str());
+    std::smatch sm;
+    if (std::regex_match(deviceNameStd, sm, kDeviceNameRE)) {
+        if (deviceVersion != nullptr) {
+            *deviceVersion = sm[1];
+        }
+        if (cameraDevicePath != nullptr) {
+            *cameraDevicePath = "/dev/video" + std::to_string(std::stoi(sm[2]) - cameraIdOffset);
+        }
+        return true;
+    }
+    return false;
+}
+
+}  // anonymous namespace
+
+ExternalCameraProviderImpl_2_7::ExternalCameraProviderImpl_2_7()
+    : mCfg(ExternalCameraConfig::loadFromCfg()) {
+    mHotPlugThread = sp<HotplugThread>::make(this);
+    mHotPlugThread->run("ExtCamHotPlug", PRIORITY_BACKGROUND);
+
+    mPreferredHal3MinorVersion =
+            property_get_int32("ro.vendor.camera.external.hal3TrebleMinorVersion", 4);
+    ALOGV("Preferred HAL 3 minor version is %d", mPreferredHal3MinorVersion);
+    switch (mPreferredHal3MinorVersion) {
+        case 4:
+        case 5:
+        case 6:
+            // OK
+            break;
+        default:
+            ALOGW("Unknown minor camera device HAL version %d in property "
+                  "'camera.external.hal3TrebleMinorVersion', defaulting to 4",
+                  mPreferredHal3MinorVersion);
+            mPreferredHal3MinorVersion = 4;
+    }
+}
+
+ExternalCameraProviderImpl_2_7::~ExternalCameraProviderImpl_2_7() {
+    mHotPlugThread->requestExit();
+}
+
+Return<Status> ExternalCameraProviderImpl_2_7::setCallback(
+        const sp<ICameraProviderCallback>& callback) {
+    Mutex::Autolock _l(mLock);
+    mCallbacks = callback;
+    if (mCallbacks == nullptr) {
+        return Status::OK;
+    }
+    // Send a callback for all devices to initialize
+    {
+        for (const auto& pair : mCameraStatusMap) {
+            mCallbacks->cameraDeviceStatusChange(pair.first, pair.second);
+        }
+    }
+
+    return Status::OK;
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::getVendorTags(
+        ICameraProvider::getVendorTags_cb _hidl_cb) {
+    // No vendor tag support for USB camera
+    hidl_vec<VendorTagSection> zeroSections;
+    _hidl_cb(Status::OK, zeroSections);
+    return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::getCameraIdList(
+        ICameraProvider::getCameraIdList_cb _hidl_cb) {
+    // External camera HAL always report 0 camera, and extra cameras
+    // are just reported via cameraDeviceStatusChange callbacks
+    hidl_vec<hidl_string> hidlDeviceNameList;
+    _hidl_cb(Status::OK, hidlDeviceNameList);
+    return Void();
+}
+
+void ExternalCameraProviderImpl_2_7::updateAttachedCameras() {
+    ALOGV("%s start scaning for existing V4L2 devices", __FUNCTION__);
+    // Find existing /dev/video* devices
+    DIR* devdir = opendir(kDevicePath);
+    if (devdir == 0) {
+        ALOGE("%s: cannot open %s! Exiting threadloop", __FUNCTION__, kDevicePath);
+        return;
+    }
+
+    struct dirent* de;
+    while ((de = readdir(devdir)) != 0) {
+        // Find external v4l devices that's existing before we start watching and add them
+        if (!strncmp(kPrefix, de->d_name, kPrefixLen)) {
+            // TODO: This might reject some valid devices. Ex: internal is 33 and a device named 3
+            //       is added.
+            std::string deviceId(de->d_name + kPrefixLen);
+            if (mCfg.mInternalDevices.count(deviceId) == 0) {
+                ALOGV("Non-internal v4l device %s found", de->d_name);
+                char v4l2DevicePath[kMaxDevicePathLen];
+                snprintf(v4l2DevicePath, kMaxDevicePathLen, "%s%s", kDevicePath, de->d_name);
+                deviceAdded(v4l2DevicePath);
+            }
+        }
+    }
+    closedir(devdir);
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::isSetTorchModeSupported(
+        ICameraProvider::isSetTorchModeSupported_cb _hidl_cb) {
+    // setTorchMode API is supported, though right now no external camera device
+    // has a flash unit.
+    _hidl_cb(Status::OK, true);
+    return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::getCameraDeviceInterface_V1_x(
+        const hidl_string&, ICameraProvider::getCameraDeviceInterface_V1_x_cb _hidl_cb) {
+    // External Camera HAL does not support HAL1
+    _hidl_cb(Status::OPERATION_NOT_SUPPORTED, nullptr);
+    return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::getCameraDeviceInterface_V3_x(
+        const hidl_string& cameraDeviceName,
+        ICameraProvider::getCameraDeviceInterface_V3_x_cb _hidl_cb) {
+    std::string cameraDevicePath, deviceVersion;
+    bool match = matchDeviceName(mCfg.cameraIdOffset, cameraDeviceName, &deviceVersion,
+                                 &cameraDevicePath);
+    if (!match) {
+        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+        return Void();
+    }
+
+    if (mCameraStatusMap.count(cameraDeviceName) == 0 ||
+        mCameraStatusMap[cameraDeviceName] != CameraDeviceStatus::PRESENT) {
+        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+        return Void();
+    }
+
+    sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl;
+    switch (mPreferredHal3MinorVersion) {
+        case 4: {
+            ALOGV("Constructing v3.4 external camera device");
+            deviceImpl =
+                    new device::V3_4::implementation::ExternalCameraDevice(cameraDevicePath, mCfg);
+            break;
+        }
+        case 5: {
+            ALOGV("Constructing v3.5 external camera device");
+            deviceImpl =
+                    new device::V3_5::implementation::ExternalCameraDevice(cameraDevicePath, mCfg);
+            break;
+        }
+        case 6: {
+            ALOGV("Constructing v3.6 external camera device");
+            deviceImpl =
+                    new device::V3_6::implementation::ExternalCameraDevice(cameraDevicePath, mCfg);
+            break;
+        }
+        default:
+            ALOGE("%s: Unknown HAL minor version %d!", __FUNCTION__, mPreferredHal3MinorVersion);
+            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+            return Void();
+    }
+
+    if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
+        ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraDevicePath.c_str());
+        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+        return Void();
+    }
+
+    IF_ALOGV() {
+        deviceImpl->getInterface()->interfaceChain(
+                [](::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+                    ALOGV("Device interface chain:");
+                    for (auto iface : interfaceChain) {
+                        ALOGV("  %s", iface.c_str());
+                    }
+                });
+    }
+
+    _hidl_cb(Status::OK, deviceImpl->getInterface());
+
+    return Void();
+}
+
+void ExternalCameraProviderImpl_2_7::addExternalCamera(const char* devName) {
+    ALOGV("ExtCam: adding %s to External Camera HAL!", devName);
+    Mutex::Autolock _l(mLock);
+    std::string deviceName;
+    std::string cameraId =
+            std::to_string(mCfg.cameraIdOffset + std::atoi(devName + kDevicePrefixLen));
+    if (mPreferredHal3MinorVersion == 6) {
+        deviceName = std::string("device@3.6/external/") + cameraId;
+    } else if (mPreferredHal3MinorVersion == 5) {
+        deviceName = std::string("device@3.5/external/") + cameraId;
+    } else {
+        deviceName = std::string("device@3.4/external/") + cameraId;
+    }
+    mCameraStatusMap[deviceName] = CameraDeviceStatus::PRESENT;
+    if (mCallbacks != nullptr) {
+        mCallbacks->cameraDeviceStatusChange(deviceName, CameraDeviceStatus::PRESENT);
+    }
+}
+
+void ExternalCameraProviderImpl_2_7::deviceAdded(const char* devName) {
+    {
+        base::unique_fd fd(::open(devName, O_RDWR));
+        if (fd.get() < 0) {
+            ALOGE("%s open v4l2 device %s failed:%s", __FUNCTION__, devName, strerror(errno));
+            return;
+        }
+
+        struct v4l2_capability capability;
+        int ret = ioctl(fd.get(), VIDIOC_QUERYCAP, &capability);
+        if (ret < 0) {
+            ALOGE("%s v4l2 QUERYCAP %s failed", __FUNCTION__, devName);
+            return;
+        }
+
+        if (!(capability.device_caps & V4L2_CAP_VIDEO_CAPTURE)) {
+            ALOGW("%s device %s does not support VIDEO_CAPTURE", __FUNCTION__, devName);
+            return;
+        }
+    }
+    // See if we can initialize ExternalCameraDevice correctly
+    sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl =
+            new device::V3_4::implementation::ExternalCameraDevice(devName, mCfg);
+    if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
+        ALOGW("%s: Attempt to init camera device %s failed!", __FUNCTION__, devName);
+        return;
+    }
+    deviceImpl.clear();
+
+    addExternalCamera(devName);
+    return;
+}
+
+void ExternalCameraProviderImpl_2_7::deviceRemoved(const char* devName) {
+    Mutex::Autolock _l(mLock);
+    std::string deviceName;
+    std::string cameraId =
+            std::to_string(mCfg.cameraIdOffset + std::atoi(devName + kDevicePrefixLen));
+    if (mPreferredHal3MinorVersion == 6) {
+        deviceName = std::string("device@3.6/external/") + cameraId;
+    } else if (mPreferredHal3MinorVersion == 5) {
+        deviceName = std::string("device@3.5/external/") + cameraId;
+    } else {
+        deviceName = std::string("device@3.4/external/") + cameraId;
+    }
+    if (mCameraStatusMap.find(deviceName) != mCameraStatusMap.end()) {
+        mCameraStatusMap.erase(deviceName);
+        if (mCallbacks != nullptr) {
+            mCallbacks->cameraDeviceStatusChange(deviceName, CameraDeviceStatus::NOT_PRESENT);
+        }
+    } else {
+        ALOGE("%s: cannot find camera device %s", __FUNCTION__, devName);
+    }
+}
+
+ExternalCameraProviderImpl_2_7::HotplugThread::HotplugThread(ExternalCameraProviderImpl_2_7* parent)
+    : Thread(/*canCallJava*/ false),
+      mParent(parent),
+      mInternalDevices(parent->mCfg.mInternalDevices) {}
+
+ExternalCameraProviderImpl_2_7::HotplugThread::~HotplugThread() {}
+
+bool ExternalCameraProviderImpl_2_7::HotplugThread::threadLoop() {
+    // Update existing cameras
+    mParent->updateAttachedCameras();
+
+    // Watch new video devices
+    mINotifyFD = inotify_init();
+    if (mINotifyFD < 0) {
+        ALOGE("%s: inotify init failed! Exiting threadloop", __FUNCTION__);
+        return true;
+    }
+
+    mWd = inotify_add_watch(mINotifyFD, kDevicePath, IN_CREATE | IN_DELETE);
+    if (mWd < 0) {
+        ALOGE("%s: inotify add watch failed! Exiting threadloop", __FUNCTION__);
+        return true;
+    }
+
+    bool done = false;
+    char eventBuf[512];
+    while (!done) {
+        int offset = 0;
+        int ret = read(mINotifyFD, eventBuf, sizeof(eventBuf));
+        if (ret >= (int)sizeof(struct inotify_event)) {
+            while (offset < ret) {
+                struct inotify_event* event = (struct inotify_event*)&eventBuf[offset];
+                if (event->wd == mWd) {
+                    ALOGV("%s inotify_event %s", __FUNCTION__, event->name);
+                    if (!strncmp(kPrefix, event->name, kPrefixLen)) {
+                        std::string deviceId(event->name + kPrefixLen);
+                        if (mInternalDevices.count(deviceId) == 0) {
+                            char v4l2DevicePath[kMaxDevicePathLen];
+                            snprintf(v4l2DevicePath, kMaxDevicePathLen, "%s%s", kDevicePath,
+                                     event->name);
+                            if (event->mask & IN_CREATE) {
+                                mParent->deviceAdded(v4l2DevicePath);
+                            }
+                            if (event->mask & IN_DELETE) {
+                                mParent->deviceRemoved(v4l2DevicePath);
+                            }
+                        }
+                    }
+                }
+                offset += sizeof(struct inotify_event) + event->len;
+            }
+        }
+    }
+
+    return true;
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::notifyDeviceStateChange(
+        hidl_bitfield<DeviceState> /*newState*/) {
+    return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::getConcurrentStreamingCameraIds(
+        ICameraProvider::getConcurrentStreamingCameraIds_cb _hidl_cb) {
+    hidl_vec<hidl_vec<hidl_string>> hidl_camera_id_combinations;
+    _hidl_cb(Status::OK, hidl_camera_id_combinations);
+    return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::isConcurrentStreamCombinationSupported(
+        const hidl_vec<::android::hardware::camera::provider::V2_6::
+                               CameraIdAndStreamCombination>& /* configs */,
+        ICameraProvider::isConcurrentStreamCombinationSupported_cb _hidl_cb) {
+    _hidl_cb(Status::OK, false);
+    return Void();
+}
+
+Return<void> ExternalCameraProviderImpl_2_7::isConcurrentStreamCombinationSupported_2_7(
+        const hidl_vec<CameraIdAndStreamCombination>& /* configs */,
+        ICameraProvider::isConcurrentStreamCombinationSupported_2_7_cb _hidl_cb) {
+    _hidl_cb(Status::OK, false);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_7
+}  // namespace provider
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.h b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.h
new file mode 100644
index 0000000..da9f6b3
--- /dev/null
+++ b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.h
@@ -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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA_PROVIDER_V2_7_EXTCAMERAPROVIDER_H
+#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_7_EXTCAMERAPROVIDER_H
+
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <utils/Mutex.h>
+#include <utils/Thread.h>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include "ExternalCameraUtils.h"
+
+#include <android/hardware/camera/provider/2.6/ICameraProviderCallback.h>
+#include <android/hardware/camera/provider/2.7/ICameraProvider.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace provider {
+namespace V2_7 {
+namespace implementation {
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::VendorTagSection;
+using ::android::hardware::camera::external::common::ExternalCameraConfig;
+using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
+using ::android::hardware::camera::provider::V2_5::DeviceState;
+using ::android::hardware::camera::provider::V2_7::CameraIdAndStreamCombination;
+using ::android::hardware::camera::provider::V2_7::ICameraProvider;
+using ::android::hidl::base::V1_0::IBase;
+
+/**
+ * The implementation of external webcam CameraProvider 2.7, separated
+ * from the HIDL interface layer to allow for implementation reuse by later
+ * provider versions.
+ *
+ * This camera provider supports standard UVC webcameras via the Linux V4L2
+ * UVC driver.
+ */
+struct ExternalCameraProviderImpl_2_7 {
+    ExternalCameraProviderImpl_2_7();
+    ~ExternalCameraProviderImpl_2_7();
+
+    // Caller must use this method to check if CameraProvider ctor failed
+    bool isInitFailed() { return false; }
+
+    // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow.
+    Return<Status> setCallback(const sp<ICameraProviderCallback>& callback);
+    Return<void> getVendorTags(ICameraProvider::getVendorTags_cb _hidl_cb);
+    Return<void> getCameraIdList(ICameraProvider::getCameraIdList_cb _hidl_cb);
+    Return<void> isSetTorchModeSupported(ICameraProvider::isSetTorchModeSupported_cb _hidl_cb);
+    Return<void> getCameraDeviceInterface_V1_x(const hidl_string&,
+                                               ICameraProvider::getCameraDeviceInterface_V1_x_cb);
+    Return<void> getCameraDeviceInterface_V3_x(const hidl_string&,
+                                               ICameraProvider::getCameraDeviceInterface_V3_x_cb);
+
+    // Methods from ::android::hardware::camera::provider::V2_5::ICameraProvider follow.
+    Return<void> notifyDeviceStateChange(hidl_bitfield<DeviceState> newState);
+
+    // Methods from ::android::hardware::camera::provider::V2_7::ICameraProvider follow.
+    Return<void> getConcurrentStreamingCameraIds(
+            ICameraProvider::getConcurrentStreamingCameraIds_cb _hidl_cb);
+
+    Return<void> isConcurrentStreamCombinationSupported(
+            const hidl_vec<
+                    ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination>&
+                    configs,
+            ICameraProvider::isConcurrentStreamCombinationSupported_cb _hidl_cb);
+
+    Return<void> isConcurrentStreamCombinationSupported_2_7(
+            const hidl_vec<CameraIdAndStreamCombination>& configs,
+            ICameraProvider::isConcurrentStreamCombinationSupported_2_7_cb _hidl_cb);
+
+  private:
+    void addExternalCamera(const char* devName);
+
+    void deviceAdded(const char* devName);
+
+    void deviceRemoved(const char* devName);
+
+    void updateAttachedCameras();
+
+    class HotplugThread : public android::Thread {
+      public:
+        HotplugThread(ExternalCameraProviderImpl_2_7* parent);
+        ~HotplugThread();
+
+        virtual bool threadLoop() override;
+
+      private:
+        ExternalCameraProviderImpl_2_7* mParent = nullptr;
+        const std::unordered_set<std::string> mInternalDevices;
+
+        int mINotifyFD = -1;
+        int mWd = -1;
+    };
+
+    Mutex mLock;
+    sp<ICameraProviderCallback> mCallbacks = nullptr;
+    std::unordered_map<std::string, CameraDeviceStatus> mCameraStatusMap;  // camera id -> status
+    const ExternalCameraConfig mCfg;
+    sp<HotplugThread> mHotPlugThread;
+    int mPreferredHal3MinorVersion;
+};
+
+}  // namespace implementation
+}  // namespace V2_7
+}  // namespace provider
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_7_EXTCAMERAPROVIDER_H
diff --git a/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service-lazy.rc b/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service-lazy.rc
new file mode 100644
index 0000000..9292c4f
--- /dev/null
+++ b/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service-lazy.rc
@@ -0,0 +1,13 @@
+service vendor.camera-provider-2-7-ext /vendor/bin/hw/android.hardware.camera.provider@2.7-external-service-lazy
+    interface android.hardware.camera.provider@2.4::ICameraProvider external/0
+    interface android.hardware.camera.provider@2.5::ICameraProvider external/0
+    interface android.hardware.camera.provider@2.6::ICameraProvider external/0
+    interface android.hardware.camera.provider@2.7::ICameraProvider external/0
+    class hal
+    oneshot
+    disabled
+    user cameraserver
+    group audio camera input drmrpc usb
+    ioprio rt 4
+    capabilities SYS_NICE
+    task_profiles CameraServiceCapacity MaxPerformance
\ No newline at end of file
diff --git a/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service.rc b/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service.rc
new file mode 100644
index 0000000..2c9b782
--- /dev/null
+++ b/camera/provider/2.7/default/android.hardware.camera.provider@2.7-external-service.rc
@@ -0,0 +1,11 @@
+service vendor.camera-provider-2-7-ext /vendor/bin/hw/android.hardware.camera.provider@2.7-external-service
+    interface android.hardware.camera.provider@2.4::ICameraProvider external/0
+    interface android.hardware.camera.provider@2.5::ICameraProvider external/0
+    interface android.hardware.camera.provider@2.6::ICameraProvider external/0
+    interface android.hardware.camera.provider@2.7::ICameraProvider external/0
+    class hal
+    user cameraserver
+    group audio camera input drmrpc usb
+    ioprio rt 4
+    capabilities SYS_NICE
+    task_profiles CameraServiceCapacity MaxPerformance
diff --git a/camera/provider/2.7/default/external-service.cpp b/camera/provider/2.7/default/external-service.cpp
new file mode 100644
index 0000000..90b8239
--- /dev/null
+++ b/camera/provider/2.7/default/external-service.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifdef LAZY_SERVICE
+#define LOG_TAG "android.hardware.camera.provider@2.7-external-service-lazy"
+#else
+#define LOG_TAG "android.hardware.camera.provider@2.7-external-service"
+#endif
+
+#include <android/hardware/camera/provider/2.7/ICameraProvider.h>
+#include <binder/ProcessState.h>
+#include <hidl/HidlLazyUtils.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "CameraProvider_2_7.h"
+#include "ExternalCameraProviderImpl_2_7.h"
+
+using android::status_t;
+using android::hardware::camera::provider::V2_7::ICameraProvider;
+using android::hidl::base::V1_0::IBase;
+
+#ifdef LAZY_SERVICE
+const bool kLazyService = true;
+#else
+const bool kLazyService = false;
+#endif
+
+int main() {
+    using namespace android::hardware::camera::provider::V2_7::implementation;
+
+    ALOGI("CameraProvider@2.7 external webcam service is starting.");
+
+    ::android::hardware::configureRpcThreadpool(/*threads*/ HWBINDER_THREAD_COUNT,
+                                                /*willJoin*/ true);
+
+    ::android::sp<CameraProvider<ExternalCameraProviderImpl_2_7>> provider =
+            new CameraProvider<ExternalCameraProviderImpl_2_7>();
+
+    status_t status;
+    if (kLazyService) {
+        auto serviceRegistrar = ::android::hardware::LazyServiceRegistrar::getInstance();
+        status = serviceRegistrar.registerService(provider, "external/0");
+    } else {
+        status = provider->registerAsService("external/0");
+    }
+
+    LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering provider service: %d",
+                        status);
+
+    ::android::hardware::joinRpcThreadpool();
+
+    return 0;
+}
\ No newline at end of file
diff --git a/common/support/Android.bp b/common/support/Android.bp
index b24893b..718901e 100644
--- a/common/support/Android.bp
+++ b/common/support/Android.bp
@@ -11,7 +11,11 @@
     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: [
@@ -28,7 +32,11 @@
 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",
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index cf85688..594f07b 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -60,6 +60,14 @@
             <regex-instance>.*</regex-instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.automotive.evs</name>
+        <interface>
+            <name>IEvsEnumerator</name>
+            <instance>default</instance>
+            <regex-instance>[a-z]+/[0-9]+</regex-instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.automotive.evs</name>
         <version>1.0-1</version>
@@ -77,14 +85,6 @@
             <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="aidl" optional="true">
         <name>android.hardware.automotive.vehicle</name>
         <interface>
@@ -110,6 +110,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.biometrics.face</name>
+        <version>2</version>
         <interface>
             <name>IFace</name>
             <instance>default</instance>
@@ -272,6 +273,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.gnss.measurement_corrections</name>
+        <version>1</version>
+        <interface>
+            <name>IMeasurementCorrectionsInterface</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 -->
@@ -328,7 +337,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>
@@ -455,7 +464,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.neuralnetworks</name>
-        <version>1-3</version>
+        <version>1-4</version>
         <interface>
             <name>IDevice</name>
             <regex-instance>.*</regex-instance>
@@ -687,7 +696,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>
@@ -777,7 +786,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi</name>
-        <version>1.3-5</version>
+        <version>1.3-6</version>
         <interface>
             <name>IWifi</name>
             <instance>default</instance>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index 2aa4bb2..414c502 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -56,6 +56,7 @@
             "android.hardware.common",
             "android.hardware.common.fmq",
             "android.hardware.graphics.common",
+            "android.hardware.input.common",
             "android.hardware.keymaster",
             "android.hardware.radio",
             "android.hardware.uwb.fira_android",
diff --git a/current.txt b/current.txt
index 1dbf5ab..1fedaa0 100644
--- a/current.txt
+++ b/current.txt
@@ -907,6 +907,7 @@
 # ABI preserving changes to HALs during Android T
 62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot
 f767a132ef28275294db15353f14f3876a4048770751931a77d038d4228f2cb7 android.hardware.graphics.composer@2.4::IComposerClient
+d0fb32f3ddeb9af7115ab32905225ea69b930d2472be8e9610f0cf136c15aefb android.hardware.keymaster@4.0::IKeymasterDevice # b/210424594
 ca62a2a95d173ed323309e5e00f653ad3cceec82a6e5e4976a249cb5aafe2515 android.hardware.neuralnetworks@1.2::types
 fa76bced6b1b71c40fc706c508a9011284c57f57831cd0cf5f45653ed4ea463e android.hardware.neuralnetworks@1.3::types
 
diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp
index c59d5e7..f8fad94 100644
--- a/gnss/1.1/vts/functional/Android.bp
+++ b/gnss/1.1/vts/functional/Android.bp
@@ -36,6 +36,7 @@
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@common-vts-lib",
+        "android.hardware.gnss-V2-cpp",
     ],
     shared_libs: [
         "android.hardware.gnss.measurement_corrections@1.0",
diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp
index 3bbd572..2042dd9 100644
--- a/gnss/2.0/vts/functional/Android.bp
+++ b/gnss/2.0/vts/functional/Android.bp
@@ -39,6 +39,10 @@
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@2.1",
         "android.hardware.gnss@common-vts-lib",
+        "android.hardware.gnss-V2-cpp",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
diff --git a/gnss/2.1/vts/functional/Android.bp b/gnss/2.1/vts/functional/Android.bp
index aaddd96..d7b6eeb 100644
--- a/gnss/2.1/vts/functional/Android.bp
+++ b/gnss/2.1/vts/functional/Android.bp
@@ -40,6 +40,7 @@
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@2.1",
         "android.hardware.gnss@common-vts-lib",
+        "android.hardware.gnss-V2-cpp",
     ],
     shared_libs: [
         "libvintf",
diff --git a/gnss/aidl/Android.bp b/gnss/aidl/Android.bp
index 12dd0ac..4d9c5cc 100644
--- a/gnss/aidl/Android.bp
+++ b/gnss/aidl/Android.bp
@@ -24,27 +24,13 @@
 }
 
 aidl_interface {
-    name: "android.hardware.gnss.visibility_control",
-    vendor_available: true,
-    srcs: ["android/hardware/gnss/visibility_control/*.aidl"],
-    stability: "vintf",
-    backend: {
-        java: {
-            platform_apis: true,
-        },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
-    },
-}
-
-aidl_interface {
     name: "android.hardware.gnss",
     vendor_available: true,
-    srcs: ["android/hardware/gnss/*.aidl"],
-    imports: ["android.hardware.gnss.visibility_control"],
+    srcs: [
+        "android/hardware/gnss/*.aidl",
+        "android/hardware/gnss/measurement_corrections/*.aidl",
+        "android/hardware/gnss/visibility_control/*.aidl",
+    ],
     stability: "vintf",
     backend: {
         java: {
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
index ebb5d0b..aa514da 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
@@ -37,4 +37,11 @@
   android.hardware.gnss.GnssMeasurement[] measurements;
   android.hardware.gnss.GnssClock clock;
   android.hardware.gnss.ElapsedRealtime elapsedRealtime;
+  @nullable android.hardware.gnss.GnssData.GnssAgc[] gnssAgcs;
+  @VintfStability
+  parcelable GnssAgc {
+    double agcLevelDb;
+    android.hardware.gnss.GnssConstellationType constellation = android.hardware.gnss.GnssConstellationType.UNKNOWN;
+    long carrierFrequencyHz;
+  }
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRil.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRil.aidl
new file mode 100644
index 0000000..73df195
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRil.aidl
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+interface IAGnssRil {
+  void setCallback(in android.hardware.gnss.IAGnssRilCallback callback);
+  void setRefLocation(in android.hardware.gnss.IAGnssRil.AGnssRefLocation agnssReflocation);
+  void setSetId(in android.hardware.gnss.IAGnssRil.SetIDType type, in @utf8InCpp String setid);
+  void updateNetworkState(in android.hardware.gnss.IAGnssRil.NetworkAttributes attributes);
+  const int NETWORK_CAPABILITY_NOT_METERED = 1;
+  const int NETWORK_CAPABILITY_NOT_ROAMING = 2;
+  @Backing(type="int") @VintfStability
+  enum AGnssRefLocationType {
+    GSM_CELLID = 1,
+    UMTS_CELLID = 2,
+    LTE_CELLID = 4,
+    NR_CELLID = 8,
+  }
+  @Backing(type="int") @VintfStability
+  enum SetIDType {
+    NONE = 0,
+    IMSI = 1,
+    MSISDM = 2,
+  }
+  @VintfStability
+  parcelable AGnssRefLocationCellID {
+    android.hardware.gnss.IAGnssRil.AGnssRefLocationType type;
+    int mcc;
+    int mnc;
+    int lac;
+    long cid;
+    int tac;
+    int pcid;
+    int arfcn;
+  }
+  @VintfStability
+  parcelable AGnssRefLocation {
+    android.hardware.gnss.IAGnssRil.AGnssRefLocationType type;
+    android.hardware.gnss.IAGnssRil.AGnssRefLocationCellID cellID;
+  }
+  @VintfStability
+  parcelable NetworkAttributes {
+    long networkHandle;
+    boolean isConnected;
+    int capabilities;
+    @utf8InCpp String apn;
+  }
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRilCallback.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRilCallback.aidl
index 295fde9..152b10a 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRilCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.gnss;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+interface IAGnssRilCallback {
+  void requestSetIdCb(in int setIdflag);
+  void requestRefLocCb();
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
index 1b4c581..a16d27b 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
@@ -44,6 +44,7 @@
   @nullable android.hardware.gnss.IGnssGeofence getExtensionGnssGeofence();
   @nullable android.hardware.gnss.IGnssNavigationMessageInterface getExtensionGnssNavigationMessage();
   android.hardware.gnss.IAGnss getExtensionAGnss();
+  android.hardware.gnss.IAGnssRil getExtensionAGnssRil();
   android.hardware.gnss.IGnssDebug getExtensionGnssDebug();
   android.hardware.gnss.visibility_control.IGnssVisibilityControl getExtensionGnssVisibilityControl();
   void start();
@@ -53,6 +54,8 @@
   void injectBestLocation(in android.hardware.gnss.GnssLocation location);
   void deleteAidingData(in android.hardware.gnss.IGnss.GnssAidingData aidingDataFlags);
   void setPositionMode(in android.hardware.gnss.IGnss.GnssPositionMode mode, in android.hardware.gnss.IGnss.GnssPositionRecurrence recurrence, in int minIntervalMs, in int preferredAccuracyMeters, in int preferredTimeMs, in boolean lowPowerMode);
+  android.hardware.gnss.IGnssAntennaInfo getExtensionGnssAntennaInfo();
+  @nullable android.hardware.gnss.measurement_corrections.IMeasurementCorrectionsInterface getExtensionMeasurementCorrections();
   const int ERROR_INVALID_ARGUMENT = 1;
   const int ERROR_ALREADY_INIT = 2;
   const int ERROR_GENERIC = 3;
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfo.aidl
similarity index 89%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfo.aidl
index 295fde9..2734ac1 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfo.aidl
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.gnss;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+interface IGnssAntennaInfo {
+  void setCallback(in android.hardware.gnss.IGnssAntennaInfoCallback callback);
+  void close();
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfoCallback.aidl
similarity index 63%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfoCallback.aidl
index 295fde9..ada9707 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfoCallback.aidl
@@ -31,12 +31,30 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.gnss;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+interface IGnssAntennaInfoCallback {
+  void gnssAntennaInfoCb(in android.hardware.gnss.IGnssAntennaInfoCallback.GnssAntennaInfo[] gnssAntennaInfos);
+  @VintfStability
+  parcelable Row {
+    double[] row;
+  }
+  @VintfStability
+  parcelable Coord {
+    double x;
+    double xUncertainty;
+    double y;
+    double yUncertainty;
+    double z;
+    double zUncertainty;
+  }
+  @VintfStability
+  parcelable GnssAntennaInfo {
+    long carrierFrequencyHz;
+    android.hardware.gnss.IGnssAntennaInfoCallback.Coord phaseCenterOffsetCoordinateMillimeters;
+    android.hardware.gnss.IGnssAntennaInfoCallback.Row[] phaseCenterVariationCorrectionMillimeters;
+    android.hardware.gnss.IGnssAntennaInfoCallback.Row[] phaseCenterVariationCorrectionUncertaintyMillimeters;
+    android.hardware.gnss.IGnssAntennaInfoCallback.Row[] signalGainCorrectionDbi;
+    android.hardware.gnss.IGnssAntennaInfoCallback.Row[] signalGainCorrectionUncertaintyDbi;
+  }
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatching.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatching.aidl
index 492edc3..e1beed3 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatching.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatching.aidl
@@ -36,9 +36,15 @@
 interface IGnssBatching {
   void init(in android.hardware.gnss.IGnssBatchingCallback callback);
   int getBatchSize();
-  void start(in long periodNanos, in int flags);
+  void start(in android.hardware.gnss.IGnssBatching.Options options);
   void flush();
   void stop();
   void cleanup();
   const int WAKEUP_ON_FIFO_FULL = 1;
+  @VintfStability
+  parcelable Options {
+    long periodNanos;
+    float minDistanceMeters;
+    int flags;
+  }
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsCallback.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsCallback.aidl
index 295fde9..c4cf13f 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsCallback.aidl
@@ -31,12 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.gnss.measurement_corrections;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+interface IMeasurementCorrectionsCallback {
+  void setCapabilitiesCb(in int capabilities);
+  const int CAPABILITY_LOS_SATS = 1;
+  const int CAPABILITY_EXCESS_PATH_LENGTH = 2;
+  const int CAPABILITY_REFLECTING_PLANE = 4;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsInterface.aidl
similarity index 83%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsInterface.aidl
index 295fde9..5dc5596 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsInterface.aidl
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.gnss.measurement_corrections;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+interface IMeasurementCorrectionsInterface {
+  void setCorrections(in android.hardware.gnss.measurement_corrections.MeasurementCorrections corrections);
+  void setCallback(in android.hardware.gnss.measurement_corrections.IMeasurementCorrectionsCallback callback);
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/MeasurementCorrections.aidl
similarity index 77%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/MeasurementCorrections.aidl
index 295fde9..f32c8c2 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/MeasurementCorrections.aidl
@@ -31,12 +31,17 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.gnss.measurement_corrections;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable MeasurementCorrections {
+  double latitudeDegrees;
+  double longitudeDegrees;
+  double altitudeMeters;
+  double horizontalPositionUncertaintyMeters;
+  double verticalPositionUncertaintyMeters;
+  long toaGpsNanosecondsOfWeek;
+  android.hardware.gnss.measurement_corrections.SingleSatCorrection[] satCorrections;
+  boolean hasEnvironmentBearing;
+  float environmentBearingDegrees;
+  float environmentBearingUncertaintyDegrees;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/ReflectingPlane.aidl
similarity index 89%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/ReflectingPlane.aidl
index 295fde9..90c3818 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/ReflectingPlane.aidl
@@ -31,12 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.gnss.measurement_corrections;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable ReflectingPlane {
+  double latitudeDegrees;
+  double longitudeDegrees;
+  double altitudeMeters;
+  double azimuthDegrees;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/SingleSatCorrection.aidl
similarity index 72%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/SingleSatCorrection.aidl
index 295fde9..d18c1a7 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/SingleSatCorrection.aidl
@@ -31,12 +31,19 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.gnss.measurement_corrections;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable SingleSatCorrection {
+  int singleSatCorrectionFlags;
+  android.hardware.gnss.GnssConstellationType constellation;
+  int svid;
+  long carrierFrequencyHz;
+  float probSatIsLos;
+  float excessPathLengthMeters;
+  float excessPathLengthUncertaintyMeters;
+  android.hardware.gnss.measurement_corrections.ReflectingPlane reflectingPlane;
+  const int SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY = 1;
+  const int SINGLE_SAT_CORRECTION_HAS_EXCESS_PATH_LENGTH = 2;
+  const int SINGLE_SAT_CORRECTION_HAS_EXCESS_PATH_LENGTH_UNC = 4;
+  const int SINGLE_SAT_CORRECTION_HAS_REFLECTING_PLANE = 8;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
similarity index 96%
rename from gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
rename to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
index 7ef08d2..f674099 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
@@ -34,6 +34,6 @@
 package android.hardware.gnss.visibility_control;
 @VintfStability
 interface IGnssVisibilityControl {
-  void enableNfwLocationAccess(in String[] proxyApps);
+  void enableNfwLocationAccess(in @utf8InCpp String[] proxyApps);
   void setCallback(in android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback callback);
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
similarity index 100%
rename from gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
rename to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
diff --git a/gnss/aidl/android/hardware/gnss/GnssData.aidl b/gnss/aidl/android/hardware/gnss/GnssData.aidl
index ed30c98..204eb65 100644
--- a/gnss/aidl/android/hardware/gnss/GnssData.aidl
+++ b/gnss/aidl/android/hardware/gnss/GnssData.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.gnss.ElapsedRealtime;
 import android.hardware.gnss.GnssClock;
+import android.hardware.gnss.GnssConstellationType;
 import android.hardware.gnss.GnssMeasurement;
 
 /**
@@ -41,4 +42,55 @@
      * clock.
      */
     ElapsedRealtime elapsedRealtime;
-}
\ No newline at end of file
+
+    /**
+     * Represents a reading of GNSS AGC value of a constellation type and a frequency band.
+     */
+    @VintfStability
+    parcelable GnssAgc {
+        /**
+         * Automatic gain control (AGC) level. AGC acts as a variable gain amplifier adjusting the
+         * power of the incoming signal. The AGC level may be used to indicate potential
+         * interference. Higher gain (and/or lower input power) must be output as a positive number.
+         * Hence in cases of strong jamming, in the band of this signal, this value must go more
+         * negative. This value must be consistent given the same level of the incoming signal
+         * power.
+         *
+         * Note: Different hardware designs (e.g. antenna, pre-amplification, or other RF HW
+         * components) may also affect the typical output of this value on any given hardware design
+         * in an open sky test - the important aspect of this output is that changes in this value
+         * are indicative of changes on input signal power in the frequency band for this
+         * measurement.
+         */
+        double agcLevelDb;
+
+        /**
+         * Constellation type of the SV that transmits the signal.
+         */
+        GnssConstellationType constellation = GnssConstellationType.UNKNOWN;
+
+        /**
+         * Carrier frequency of the signal tracked, for example it can be the
+         * GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz, L5 =
+         * 1176.45 MHz, varying GLO channels, etc. If the field is not set, it
+         * is the primary common use central frequency, e.g. L1 = 1575.45 MHz
+         * for GPS.
+         *
+         * For an L1, L5 receiver tracking a satellite on L1 and L5 at the same
+         * time, two raw measurement structs must be reported for this same
+         * satellite, in one of the measurement structs, all the values related
+         * to L1 must be filled, and in the other all of the values related to
+         * L5 must be filled.
+         */
+        long carrierFrequencyHz;
+    }
+
+    /**
+     * The array of GNSS AGC values.
+     *
+     * This field must be reported when the GNSS measurement engine is running, even when the
+     * GnssMeasurement or GnssClock fields are not reported yet. E.g., when a GNSS signal is too
+     * weak to be acquired, the AGC value must still be reported.
+     */
+    @nullable GnssAgc[] gnssAgcs;
+}
diff --git a/gnss/aidl/android/hardware/gnss/IAGnssRil.aidl b/gnss/aidl/android/hardware/gnss/IAGnssRil.aidl
new file mode 100644
index 0000000..c506b04
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IAGnssRil.aidl
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.IAGnssRilCallback;
+import android.hardware.gnss.IAGnssRilCallback.SetIDType;
+
+/**
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface
+ * Layer interface allows the GNSS chipset to request radio interface layer
+ * information from Android platform. Examples of such information are reference
+ * location, unique subscriber ID, phone number string and network availability changes.
+ */
+@VintfStability
+interface IAGnssRil {
+    /** Network capability mode bitmask for not metered. */
+    const int NETWORK_CAPABILITY_NOT_METERED = 0x01;
+
+    /** Network capability mode bitmask for not roaming. */
+    const int NETWORK_CAPABILITY_NOT_ROAMING = 0x02;
+
+    /** AGNSS reference location type */
+    @VintfStability
+    @Backing(type="int")
+    enum AGnssRefLocationType {
+        GSM_CELLID = 1,
+        UMTS_CELLID = 2,
+        LTE_CELLID = 4,
+        NR_CELLID = 8,
+    }
+
+    /** SET ID type*/
+    @VintfStability
+    @Backing(type="int")
+    enum SetIDType {
+        NONE = 0,
+        IMSI = 1,
+        MSISDM = 2,
+    }
+
+    /**
+     * CellID for 2G, 3G ,LTE and NR used in AGNSS. This is defined in
+     * UserPlane Location Protocol (Version 2.0.4).
+     */
+    @VintfStability
+    parcelable AGnssRefLocationCellID {
+        AGnssRefLocationType type;
+
+        /** Mobile Country Code. */
+        int mcc;
+
+        /** Mobile Network Code .*/
+        int mnc;
+
+        /**
+         * Location Area Code in 2G, 3G and LTE. In 3G lac is discarded. In LTE,
+         * lac is populated with tac, to ensure that we don't break old clients that
+         * might rely on the old (wrong) behavior.
+         */
+        int lac;
+
+        /**
+         *  Cell id in 2G. Utran Cell id in 3G. Cell Global Id EUTRA in LTE.
+         *  Cell Global Id NR in 5G.
+         */
+        long cid;
+
+        /** Tracking Area Code in LTE and NR. */
+        int tac;
+
+        /** Physical Cell id in LTE and NR (not used in 2G and 3G) */
+        int pcid;
+
+        /** Absolute Radio Frequency Channel Number in NR. */
+        int arfcn;
+    }
+
+    /** Represents ref locations */
+    @VintfStability
+    parcelable AGnssRefLocation {
+        AGnssRefLocationType type;
+
+        AGnssRefLocationCellID cellID;
+    }
+
+    /** Represents network connection status and capabilities. */
+    @VintfStability
+    parcelable NetworkAttributes {
+        /** Network handle of the network for use with the NDK API. */
+        long networkHandle;
+
+        /**
+         * True indicates that network connectivity exists and it is possible to
+         * establish connections and pass data. If false, only the networkHandle field
+         * is populated to indicate that this network has just disconnected.
+         */
+        boolean isConnected;
+
+        /**
+         * A bitfield of flags indicating the capabilities of this network. The bit masks are
+         * defined in NETWORK_CAPABILITY_*.
+         */
+        int capabilities;
+
+        /**
+         * Telephony preferred Access Point Name to use for carrier data connection when
+         * connected to a cellular network. Empty string, otherwise.
+         */
+        @utf8InCpp String apn;
+    }
+
+    /**
+     * Opens the AGNSS interface and provides the callback routines
+     * to the implementation of this interface.
+     *
+     * @param callback Interface for AGnssRil callbacks.
+     *
+     */
+    void setCallback(in IAGnssRilCallback callback);
+
+    /**
+     * Sets the reference location.
+     *
+     * @param agnssReflocation AGNSS reference location CellID.
+     *
+     */
+    void setRefLocation(in AGnssRefLocation agnssReflocation);
+
+    /**
+     * Sets the SET ID.
+     *
+     * @param type Must be populated with either IMSI or MSISDN or NONE.
+     * @param setid If type is IMSI then setid is populated with
+     * a string representing the unique Subscriber ID, for example, the IMSI for
+     * a GMS phone. If type is MSISDN, then setid must contain
+     * the phone number string for line 1. For example, the MSISDN for a GSM phone.
+     * If the type is NONE, then the string must be empty.
+     *
+     */
+    void setSetId(in SetIDType type, in @utf8InCpp String setid);
+
+    /**
+     * Notifies GNSS of network status changes.
+     *
+     * The framework calls this method to update the GNSS HAL implementation of network
+     * state changes.
+     *
+     * @param attributes Updated network attributes.
+     *
+     */
+    void updateNetworkState(in NetworkAttributes attributes);
+}
diff --git a/gnss/aidl/android/hardware/gnss/IAGnssRilCallback.aidl b/gnss/aidl/android/hardware/gnss/IAGnssRilCallback.aidl
new file mode 100644
index 0000000..6fb093e
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IAGnssRilCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+/**
+ * Callback for IAGnssRil interface. Used to request SET ID and
+ * Reference Location.
+ */
+@VintfStability
+interface IAGnssRilCallback {
+    /**
+     * The Hal uses this API to request a SET ID.
+     *
+     * @param setIdflag A bitfield of IAGnssRil.SetIDType that is required by
+     * the HAL. The framework will inject an empty SET ID if the flag is NONE.
+     *
+     */
+    void requestSetIdCb(in int setIdflag);
+
+    /**
+     * The Hal uses this API to request a reference location.
+     */
+    void requestRefLocCb();
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
index 4ddc6a6..99f2ee4 100644
--- a/gnss/aidl/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -18,6 +18,8 @@
 
 import android.hardware.gnss.GnssLocation;
 import android.hardware.gnss.IAGnss;
+import android.hardware.gnss.IAGnssRil;
+import android.hardware.gnss.IGnssAntennaInfo;
 import android.hardware.gnss.IGnssBatching;
 import android.hardware.gnss.IGnssCallback;
 import android.hardware.gnss.IGnssConfiguration;
@@ -27,6 +29,7 @@
 import android.hardware.gnss.IGnssNavigationMessageInterface;
 import android.hardware.gnss.IGnssPowerIndication;
 import android.hardware.gnss.IGnssPsds;
+import android.hardware.gnss.measurement_corrections.IMeasurementCorrectionsInterface;
 import android.hardware.gnss.visibility_control.IGnssVisibilityControl;
 
 /**
@@ -186,6 +189,13 @@
     IAGnss getExtensionAGnss();
 
     /**
+     * This method returns the IAGnssRil interface.
+     *
+     * @return The IAGnssRil interface.
+     */
+    IAGnssRil getExtensionAGnssRil();
+
+    /**
      * This method returns the IGnssDebug interface.
      *
      * This method must return non-null.
@@ -277,4 +287,18 @@
     void setPositionMode(in GnssPositionMode mode, in GnssPositionRecurrence recurrence,
             in int minIntervalMs, in int preferredAccuracyMeters, in int preferredTimeMs,
             in boolean lowPowerMode);
+
+    /*
+     * This method returns the IGnssAntennaInfo.
+     *
+     * @return Handle to the IGnssAntennaInfo.
+     */
+    IGnssAntennaInfo getExtensionGnssAntennaInfo();
+
+    /**
+     * This method returns the IMeasurementCorrectionsInterface.
+     *
+     * @return Handle to the IMeasurementCorrectionsInterface.
+     */
+    @nullable IMeasurementCorrectionsInterface getExtensionMeasurementCorrections();
 }
diff --git a/gnss/aidl/android/hardware/gnss/IGnssAntennaInfo.aidl b/gnss/aidl/android/hardware/gnss/IGnssAntennaInfo.aidl
new file mode 100644
index 0000000..de83b67
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssAntennaInfo.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.gnss;
+
+import android.hardware.gnss.IGnssAntennaInfoCallback;
+
+/**
+ * Extended interface for GNSS antenna information support.
+ */
+@VintfStability
+interface IGnssAntennaInfo {
+    /**
+     * Registers the callback routines with the HAL.
+     *
+     * @param callback Handle to the GnssAntennaInfo callback interface.
+     */
+    void setCallback(in IGnssAntennaInfoCallback callback);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to close(), the previously registered callbacks must be
+     * considered invalid by the HAL.
+     * If close() is invoked without a previous setCallback, this function must perform
+     * no work.
+     */
+    void close();
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssAntennaInfoCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssAntennaInfoCallback.aidl
new file mode 100644
index 0000000..ef0a7fc
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssAntennaInfoCallback.aidl
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+/**
+ * The callback interface to report GNSS antenna information from the HAL.
+ */
+@VintfStability
+interface IGnssAntennaInfoCallback {
+    /**
+     * A row of doubles. This is used to represent a row in a 2D array, which are used to
+     * characterize the phase center variation corrections and signal gain corrections.
+     */
+    @VintfStability
+    parcelable Row {
+        double[] row;
+    }
+
+    /**
+     * A point in 3D space, with associated uncertainty.
+     */
+    @VintfStability
+    parcelable Coord {
+        double x;
+
+        double xUncertainty;
+
+        double y;
+
+        double yUncertainty;
+
+        double z;
+
+        double zUncertainty;
+    }
+
+    @VintfStability
+    parcelable GnssAntennaInfo {
+        /**
+         * The carrier frequency in Hz.
+         */
+        long carrierFrequencyHz;
+
+        /**
+         * Phase center offset (PCO) with associated 1-sigma uncertainty. PCO is defined with
+         * respect to the origin of the Android sensor coordinate system, e.g., center of primary
+         * screen for mobiles - see sensor or form factor documents for details.
+         */
+        Coord phaseCenterOffsetCoordinateMillimeters;
+
+        /**
+         * 2D vectors representing the phase center variation (PCV) corrections, in
+         * millimeters, at regularly spaced azimuthal angle (theta) and zenith angle
+         * (phi). The PCV correction is added to the phase measurement to obtain the
+         * corrected value.
+         *
+         * The azimuthal angle, theta, is defined with respect to the X axis of the
+         * Android sensor coordinate system, increasing toward the Y axis. The zenith
+         * angle, phi, is defined with respect to the Z axis of the Android Sensor
+         * coordinate system, increasing toward the X-Y plane.
+         *
+         * Each row vector (outer vectors) represents a fixed theta. The first row
+         * corresponds to a theta angle of 0 degrees. The last row corresponds to a
+         * theta angle of (360 - deltaTheta) degrees, where deltaTheta is the regular
+         * spacing between azimuthal angles, i.e., deltaTheta = 360 / (number of rows).
+         *
+         * The columns (inner vectors) represent fixed zenith angles, beginning at 0
+         * degrees and ending at 180 degrees. They are separated by deltaPhi, the regular
+         * spacing between zenith angles, i.e., deltaPhi = 180 / (number of columns - 1).
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        Row[] phaseCenterVariationCorrectionMillimeters;
+
+        /**
+         * 2D vectors of 1-sigma uncertainty in millimeters associated with the PCV
+         * correction values.
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        Row[] phaseCenterVariationCorrectionUncertaintyMillimeters;
+
+        /**
+         * 2D vectors representing the signal gain corrections at regularly spaced
+         * azimuthal angle (theta) and zenith angle (phi). The values are calculated or
+         * measured at the antenna feed point without considering the radio and receiver
+         * noise figure and path loss contribution, in dBi, i.e., decibel over isotropic
+         * antenna with the same total power. The signal gain correction is added the
+         * signal gain measurement to obtain the corrected value.
+         *
+         * The azimuthal angle, theta, is defined with respect to the X axis of the
+         * Android sensor coordinate system, increasing toward the Y axis. The zenith
+         * angle, phi, is defined with respect to the Z axis of the Android Sensor
+         * coordinate system, increasing toward the X-Y plane.
+         *
+         * Each row vector (outer vectors) represents a fixed theta. The first row
+         * corresponds to a theta angle of 0 degrees. The last row corresponds to a
+         * theta angle of (360 - deltaTheta) degrees, where deltaTheta is the regular
+         * spacing between azimuthal angles, i.e., deltaTheta = 360 / (number of rows).
+         *
+         * The columns (inner vectors) represent fixed zenith angles, beginning at 0
+         * degrees and ending at 180 degrees. They are separated by deltaPhi, the regular
+         * spacing between zenith angles, i.e., deltaPhi = 180 / (number of columns - 1).
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        Row[] signalGainCorrectionDbi;
+
+        /**
+         * 2D vectors of 1-sigma uncertainty in dBi associated with the signal
+         * gain correction values.
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        Row[] signalGainCorrectionUncertaintyDbi;
+    }
+
+    /**
+     * Called when on connection, and on known-change to these values, such as upon a known
+     * GNSS RF antenna tuning change, or a foldable device state change.
+     *
+     * This is optional. It can never be called if the GNSS antenna information is not
+     * available.
+     */
+    void gnssAntennaInfoCb(in GnssAntennaInfo[] gnssAntennaInfos);
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssBatching.aidl b/gnss/aidl/android/hardware/gnss/IGnssBatching.aidl
index 0d48ee1..0d03a0f 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssBatching.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssBatching.aidl
@@ -46,6 +46,25 @@
      */
     const int WAKEUP_ON_FIFO_FULL = 0x01;
 
+    /** Options specifying the batching request. */
+    @VintfStability
+    parcelable Options {
+        /** Time interval between samples in the location batch, in nanoseconds. */
+        long periodNanos;
+
+        /**
+         * The minimum distance in meters that the batching engine should
+         * accumulate before trying another GPS fix when in a challenging GPS environment.
+         *
+         * This is an optional field. If it is set as 0, the chipset can operate in an automatic
+         * mode.
+         */
+        float minDistanceMeters;
+
+        /** A bit field of Flags (WAKEUP_ON_FIFO_FULL) indicating the batching behavior. */
+        int flags;
+    }
+
     /**
      * Open the interface and provides the callback routines to the implementation of this
      * interface.
@@ -83,10 +102,9 @@
      * for using flushBatchedLocation to explicitly ask for the location as needed, to avoid it
      * being dropped.
      *
-     * @param periodNanos  Time interval between samples in the location batch, in nanoseconds
-     * @param flags  A bitfield of flags (WAKEUP_ON_FIFO_FULL) indicating the batching behavior
+     * @param options  Options specifying the batching request.
      */
-    void start(in long periodNanos, in int flags);
+    void start(in Options options);
 
     /**
      * Retrieve all batched locations currently stored.
diff --git a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
index 157c912..a74d097 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
@@ -67,7 +67,7 @@
     /** Capability bit mask indicating that GNSS supports measurement corrections */
     const int CAPABILITY_MEASUREMENT_CORRECTIONS = 1 << 10;
 
-    /** Capability bit mask indicating that GNSS supports measurement corrections */
+    /** Capability bit mask indicating that GNSS supports antenna info */
     const int CAPABILITY_ANTENNA_INFO = 1 << 11;
 
     /** Capability bit mask indicating that GNSS supports correlation vector */
diff --git a/gnss/aidl/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsCallback.aidl b/gnss/aidl/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsCallback.aidl
new file mode 100644
index 0000000..d695e70
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsCallback.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.gnss.measurement_corrections;
+
+/**
+ * GNSS measurement corrections callback interface.
+ */
+@VintfStability
+interface IMeasurementCorrectionsCallback {
+    /**
+     * Flags to indicate supported measurement corrections capabilities
+     *
+     * Either the LOS_SATS or the EXCESS_PATH_LENGTH capability must be supported.
+     */
+    /**
+     * Capability bit flag indicating that GNSS supports line-of-sight satellite identification
+     * measurement corrections
+     */
+    const int CAPABILITY_LOS_SATS = 1 << 0;
+    /**
+     * Capability bit flag indicating that GNSS supports per satellite excess-path-length
+     * measurement corrections
+     */
+    const int CAPABILITY_EXCESS_PATH_LENGTH = 1 << 1;
+    /**
+     * Capability bit flag indicating that GNSS supports reflecting planes measurement
+     * corrections
+     */
+    const int CAPABILITY_REFLECTING_PLANE = 1 << 2;
+
+    /**
+     * Callback to inform framework the measurement correction specific capabilities of the GNSS
+     * HAL implementation.
+     *
+     * The GNSS HAL must call this method immediately after the framework opens the measurement
+     * corrections interface.
+     *
+     * @param capabilities A bit field of flags indicating the capabilities of measurement
+     *         corrections.
+     *        It is mandatory to support either LOS_STATS or EXCESS_PATH_LENGTH capability.
+     */
+    void setCapabilitiesCb(in int capabilities);
+}
diff --git a/gnss/aidl/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsInterface.aidl b/gnss/aidl/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsInterface.aidl
new file mode 100644
index 0000000..eeabc6d
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsInterface.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.
+ */
+
+package android.hardware.gnss.measurement_corrections;
+
+import android.hardware.gnss.measurement_corrections.IMeasurementCorrectionsCallback;
+import android.hardware.gnss.measurement_corrections.MeasurementCorrections;
+
+/**
+ * Interface for measurement corrections support.
+ */
+@VintfStability
+interface IMeasurementCorrectionsInterface {
+    /**
+     * Injects measurement corrections to be used by the HAL to improve the GNSS location output.
+     *
+     * These are NOT to be used to adjust the IGnssMeasurementCallback output values -
+     * those remain raw, uncorrected measurements.
+     *
+     * In general, these are injected when conditions defined by the platform are met, such as when
+     * GNSS Location is being requested at a sufficiently high accuracy, based on the capabilities
+     * of the GNSS chipset as reported in the IGnssCallback.
+     *
+     * @param corrections The computed corrections to be used by the HAL.
+     */
+    void setCorrections(in MeasurementCorrections corrections);
+
+    /**
+     * Opens the interface and provides the callback routines to the implementation of this
+     * interface.
+     *
+     * @param callback Callback interface for IMeasurementCorrections.
+     */
+    void setCallback(in IMeasurementCorrectionsCallback callback);
+}
diff --git a/gnss/aidl/android/hardware/gnss/measurement_corrections/MeasurementCorrections.aidl b/gnss/aidl/android/hardware/gnss/measurement_corrections/MeasurementCorrections.aidl
new file mode 100644
index 0000000..285c7d4
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/measurement_corrections/MeasurementCorrections.aidl
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss.measurement_corrections;
+
+import android.hardware.gnss.measurement_corrections.SingleSatCorrection;
+
+/**
+ * A struct containing a set of measurement corrections for all used GNSS satellites at the location
+ * specified by latitudeDegrees, longitudeDegrees, altitudeMeters and at the time of week specified
+ * toaGpsNanosecondsOfWeek
+ */
+@VintfStability
+parcelable MeasurementCorrections {
+    /** Represents latitude in degrees at which the corrections are computed.. */
+    double latitudeDegrees;
+
+    /** Represents longitude in degrees at which the corrections are computed.. */
+    double longitudeDegrees;
+
+    /**
+     * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections
+     * are computed.
+     */
+    double altitudeMeters;
+
+    /**
+     * Represents the horizontal uncertainty (63% to 68% confidence) in meters on the device
+     * position at which the corrections are provided.
+     *
+     * This value is useful for example to judge how accurate the provided corrections are.
+     */
+    double horizontalPositionUncertaintyMeters;
+
+    /**
+     * Represents the vertical uncertainty (63% to 68% confidence) in meters on the device position
+     * at which the corrections are provided.
+     *
+     * This value is useful for example to judge how accurate the provided corrections are.
+     */
+    double verticalPositionUncertaintyMeters;
+
+    /** Time Of Applicability, GPS time of week in nanoseconds. */
+    long toaGpsNanosecondsOfWeek;
+
+    /**
+     * A set of SingleSatCorrection each containing measurement corrections for a satellite in view
+     */
+    SingleSatCorrection[] satCorrections;
+
+    /**
+     * Boolean indicating if environment bearing is available.
+     */
+    boolean hasEnvironmentBearing;
+
+    /**
+     * Environment bearing in degrees clockwise from true North (0.0 to 360.0], in direction of
+     * user motion. Environment bearing is provided when it is known with high probability that
+     * velocity is aligned with an environment feature, such as a building or road.
+     *
+     * If user speed is zero, environmentBearingDegrees represents bearing of most recent speed
+     * that was > 0.
+     *
+     * As position approaches another road, environmentBearingUncertaintyDegrees will grow, and at
+     * some stage hasEnvironmentBearing = false.
+     *
+     * As position moves towards an open area, environmentBearingUncertaintyDegrees will grow, and
+     * at some stage hasEnvironmentBearing = false.
+     *
+     * If the road is curved in the vicinity of the user location, then
+     * environmentBearingUncertaintyDegrees will include the amount by which the road direction
+     * changes in the area of position uncertainty.
+     *
+     * hasEnvironmentBearing should be checked to verify the environment bearing is available
+     * before calling this method. The value is undefined if hasEnvironmentBearing is false.
+     */
+    float environmentBearingDegrees;
+
+    /**
+     * Environment bearing uncertainty [0 to 180]. It represents the standard deviation of the
+     * physical structure in the circle of position uncertainty. hasEnvironmentBearing becomes false
+     * as the uncertainty value passes a predefined threshold depending on the physical structure
+     * around the user.
+     *
+     * hasEnvironmentBearing should be checked to verify the environment bearing is available
+     * before calling this method. The value is undefined if hasEnvironmentBearing is false.
+     */
+    float environmentBearingUncertaintyDegrees;
+}
diff --git a/gnss/aidl/android/hardware/gnss/measurement_corrections/ReflectingPlane.aidl b/gnss/aidl/android/hardware/gnss/measurement_corrections/ReflectingPlane.aidl
new file mode 100644
index 0000000..9bf2b44
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/measurement_corrections/ReflectingPlane.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.gnss.measurement_corrections;
+
+/**
+ * A struct containing the characteristics of the reflecting plane that the satellite signal has
+ * bounced from.
+ *
+ * The value is only valid if HAS_REFLECTING_PLANE flag is set. An invalid reflecting plane
+ * means either reflection planes serving is not supported or the satellite signal has gone
+ * through multiple reflections.
+ */
+@VintfStability
+parcelable ReflectingPlane {
+    /** Represents latitude of the reflecting plane in degrees. */
+    double latitudeDegrees;
+
+    /** Represents longitude of the reflecting plane in degrees. */
+    double longitudeDegrees;
+
+    /**
+     * Represents altitude of the reflecting point in the plane in meters above the WGS 84 reference
+     * ellipsoid.
+     */
+    double altitudeMeters;
+
+    /** Represents azimuth clockwise from north of the reflecting plane in degrees. */
+    double azimuthDegrees;
+}
diff --git a/gnss/aidl/android/hardware/gnss/measurement_corrections/SingleSatCorrection.aidl b/gnss/aidl/android/hardware/gnss/measurement_corrections/SingleSatCorrection.aidl
new file mode 100644
index 0000000..d9f7105
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/measurement_corrections/SingleSatCorrection.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.gnss.measurement_corrections;
+
+import android.hardware.gnss.GnssConstellationType;
+import android.hardware.gnss.measurement_corrections.ReflectingPlane;
+
+/**
+ * A struct with measurement corrections for a single visible satellites
+ *
+ * The bit mask singleSatCorrectionFlags indicates which correction values are valid in the struct
+ */
+@VintfStability
+parcelable SingleSatCorrection {
+    /** Bit mask to indicate which values are valid in a SingleSatCorrection object. */
+    /** GnssSingleSatCorrectionFlags has valid satellite-is-line-of-sight-probability field. */
+    const int SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY = 0x0001;
+    /** GnssSingleSatCorrectionFlags has valid Excess Path Length field. */
+    const int SINGLE_SAT_CORRECTION_HAS_EXCESS_PATH_LENGTH = 0x0002;
+    /** GnssSingleSatCorrectionFlags has valid Excess Path Length Uncertainty field. */
+    const int SINGLE_SAT_CORRECTION_HAS_EXCESS_PATH_LENGTH_UNC = 0x0004;
+    /** GnssSingleSatCorrectionFlags has valid Reflecting Plane field. */
+    const int SINGLE_SAT_CORRECTION_HAS_REFLECTING_PLANE = 0x0008;
+
+    /** Contains GnssSingleSatCorrectionFlags bits. */
+    int singleSatCorrectionFlags;
+
+    /**
+     * Defines the constellation of the given satellite.
+     */
+    GnssConstellationType constellation;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     */
+    int svid;
+
+    /**
+     * Carrier frequency of the signal to be corrected, for example it can be the
+     * GPS center frequency for L1 = 1,575,420,000 Hz, varying GLO channels, etc.
+     *
+     * For a receiver with capabilities to track multiple frequencies for the same satellite,
+     * multiple corrections for the same satellite may be provided.
+     */
+    long carrierFrequencyHz;
+
+    /**
+     * The probability that the satellite is estimated to be in Line-of-Sight condition at the given
+     * location.
+     */
+    float probSatIsLos;
+
+    /**
+     * Excess path length to be subtracted from pseudorange before using it in calculating location.
+     *
+     * Note this value is NOT to be used to adjust the GnsseasurementCallback outputs.
+     */
+    float excessPathLengthMeters;
+
+    /** Error estimate (1-sigma) for the Excess path length estimate */
+    float excessPathLengthUncertaintyMeters;
+
+    /**
+     * Defines the reflecting plane characteristics such as location and azimuth
+     *
+     * The value is only valid if HAS_REFLECTING_PLANE flag is set. An invalid reflecting plane
+     * means either reflection planes serving is not supported or the satellite signal has gone
+     * through multiple reflections.
+     */
+    ReflectingPlane reflectingPlane;
+}
diff --git a/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
index 93c3f2c..c9c1549 100644
--- a/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
+++ b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
@@ -71,7 +71,7 @@
      * The package name of the proxy Android application follows the standard Java language
      * package naming format. For example, com.example.myapp.
      */
-    void enableNfwLocationAccess(in String[] proxyApps);
+    void enableNfwLocationAccess(in @utf8InCpp String[] proxyApps);
 
     /**
      * Registers the callback for HAL implementation to use.
diff --git a/gnss/aidl/default/AGnssRil.cpp b/gnss/aidl/default/AGnssRil.cpp
new file mode 100644
index 0000000..afe0039
--- /dev/null
+++ b/gnss/aidl/default/AGnssRil.cpp
@@ -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.
+ */
+
+#define LOG_TAG "AGnssRilAidl"
+
+#include "AGnssRil.h"
+#include <inttypes.h>
+#include <log/log.h>
+
+namespace aidl::android::hardware::gnss {
+
+std::shared_ptr<IAGnssRilCallback> AGnssRil::sCallback = nullptr;
+
+ndk::ScopedAStatus AGnssRil::setCallback(const std::shared_ptr<IAGnssRilCallback>& callback) {
+    ALOGD("AGnssRil::setCallback");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AGnssRil::setRefLocation(const AGnssRefLocation& agnssReflocation) {
+    const AGnssRefLocationCellID& cellInfo = agnssReflocation.cellID;
+    ALOGD("AGnssRil::setRefLocation: type: %s, mcc: %d, mnc: %d, lac: %d, cid: %" PRId64
+          ", tac: %d, pcid: "
+          "%d, arfcn: %d",
+          toString(agnssReflocation.type).c_str(), cellInfo.mcc, cellInfo.mnc, cellInfo.lac,
+          cellInfo.cid, cellInfo.tac, cellInfo.pcid, cellInfo.arfcn);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AGnssRil::setSetId(SetIDType type, const std::string& setid) {
+    ALOGD("AGnssRil::setSetId: type:%s, setid: %s", toString(type).c_str(), setid.c_str());
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AGnssRil::updateNetworkState(const NetworkAttributes& attributes) {
+    ALOGD("AGnssRil::updateNetworkState: networkHandle:%" PRId64
+          ", isConnected: %d, capabilities: %d, "
+          "apn: %s",
+          attributes.networkHandle, attributes.isConnected, attributes.capabilities,
+          attributes.apn.c_str());
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/AGnssRil.h b/gnss/aidl/default/AGnssRil.h
new file mode 100644
index 0000000..7e429ee
--- /dev/null
+++ b/gnss/aidl/default/AGnssRil.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/gnss/BnAGnssRil.h>
+
+namespace aidl::android::hardware::gnss {
+
+struct AGnssRil : public BnAGnssRil {
+  public:
+    ndk::ScopedAStatus setCallback(const std::shared_ptr<IAGnssRilCallback>& callback) override;
+    ndk::ScopedAStatus setRefLocation(const AGnssRefLocation& agnssReflocation) override;
+    ndk::ScopedAStatus setSetId(SetIDType type, const std::string& setid) override;
+    ndk::ScopedAStatus updateNetworkState(const NetworkAttributes& attributes) override;
+
+  private:
+    // Synchronization lock for sCallback
+    mutable std::mutex mMutex;
+    // Guarded by mMutex
+    static std::shared_ptr<IAGnssRilCallback> sCallback;
+};
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
index 29c26d1..4543665 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -52,12 +52,13 @@
         "android.hardware.gnss.measurement_corrections@1.1",
         "android.hardware.gnss.measurement_corrections@1.0",
         "android.hardware.gnss.visibility_control@1.0",
-        "android.hardware.gnss.visibility_control-V1-ndk",
         "android.hardware.gnss-V2-ndk",
     ],
     srcs: [
+        "AGnssRil.cpp",
         "AGnss.cpp",
         "Gnss.cpp",
+        "GnssAntennaInfo.cpp",
         "GnssBatching.cpp",
         "GnssDebug.cpp",
         "GnssGeofence.cpp",
@@ -68,6 +69,7 @@
         "GnssConfiguration.cpp",
         "GnssMeasurementInterface.cpp",
         "GnssVisibilityControl.cpp",
+        "MeasurementCorrectionsInterface.cpp",
         "service.cpp",
     ],
     static_libs: [
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index 6578778..6331dfd 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -20,7 +20,9 @@
 #include <inttypes.h>
 #include <log/log.h>
 #include "AGnss.h"
+#include "AGnssRil.h"
 #include "DeviceFileReader.h"
+#include "GnssAntennaInfo.h"
 #include "GnssBatching.h"
 #include "GnssConfiguration.h"
 #include "GnssDebug.h"
@@ -29,6 +31,7 @@
 #include "GnssNavigationMessageInterface.h"
 #include "GnssPsds.h"
 #include "GnssVisibilityControl.h"
+#include "MeasurementCorrectionsInterface.h"
 #include "NmeaFixInfo.h"
 #include "Utils.h"
 
@@ -169,7 +172,7 @@
     return ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Gnss::getExtensionAGnss(std::shared_ptr<IAGnss>* iAGnss) {
+ScopedAStatus Gnss::getExtensionAGnss(std::shared_ptr<IAGnss>* iAGnss) {
     ALOGD("Gnss::getExtensionAGnss");
     *iAGnss = SharedRefBase::make<AGnss>();
     return ndk::ScopedAStatus::ok();
@@ -181,6 +184,12 @@
     return ScopedAStatus::ok();
 }
 
+ScopedAStatus Gnss::getExtensionAGnssRil(std::shared_ptr<IAGnssRil>* iAGnssRil) {
+    ALOGD("Gnss::getExtensionAGnssRil");
+    *iAGnssRil = SharedRefBase::make<AGnssRil>();
+    return ndk::ScopedAStatus::ok();
+}
+
 ScopedAStatus Gnss::injectLocation(const GnssLocation& location) {
     ALOGD("injectLocation. lat:%lf, lng:%lf, acc:%f", location.latitudeDegrees,
           location.longitudeDegrees, location.horizontalAccuracyMeters);
@@ -279,4 +288,22 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Gnss::getExtensionGnssAntennaInfo(
+        std::shared_ptr<IGnssAntennaInfo>* iGnssAntennaInfo) {
+    ALOGD("Gnss::getExtensionGnssAntennaInfo");
+
+    *iGnssAntennaInfo = SharedRefBase::make<GnssAntennaInfo>();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Gnss::getExtensionMeasurementCorrections(
+        std::shared_ptr<measurement_corrections::IMeasurementCorrectionsInterface>*
+                iMeasurementCorrections) {
+    ALOGD("Gnss::getExtensionMeasurementCorrections");
+
+    *iMeasurementCorrections =
+            SharedRefBase::make<measurement_corrections::MeasurementCorrectionsInterface>();
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h
index f21d756..36874b8 100644
--- a/gnss/aidl/default/Gnss.h
+++ b/gnss/aidl/default/Gnss.h
@@ -17,13 +17,16 @@
 #pragma once
 
 #include <aidl/android/hardware/gnss/BnAGnss.h>
+#include <aidl/android/hardware/gnss/BnAGnssRil.h>
 #include <aidl/android/hardware/gnss/BnGnss.h>
+#include <aidl/android/hardware/gnss/BnGnssAntennaInfo.h>
 #include <aidl/android/hardware/gnss/BnGnssBatching.h>
 #include <aidl/android/hardware/gnss/BnGnssConfiguration.h>
 #include <aidl/android/hardware/gnss/BnGnssDebug.h>
 #include <aidl/android/hardware/gnss/BnGnssMeasurementInterface.h>
 #include <aidl/android/hardware/gnss/BnGnssPowerIndication.h>
 #include <aidl/android/hardware/gnss/BnGnssPsds.h>
+#include <aidl/android/hardware/gnss/measurement_corrections/BnMeasurementCorrectionsInterface.h>
 #include <aidl/android/hardware/gnss/visibility_control/BnGnssVisibilityControl.h>
 #include <atomic>
 #include <mutex>
@@ -65,10 +68,17 @@
     ndk::ScopedAStatus getExtensionGnssNavigationMessage(
             std::shared_ptr<IGnssNavigationMessageInterface>* iGnssNavigationMessage) override;
     ndk::ScopedAStatus getExtensionAGnss(std::shared_ptr<IAGnss>* iAGnss) override;
+    ndk::ScopedAStatus getExtensionAGnssRil(std::shared_ptr<IAGnssRil>* iAGnssRil) override;
     ndk::ScopedAStatus getExtensionGnssDebug(std::shared_ptr<IGnssDebug>* iGnssDebug) override;
     ndk::ScopedAStatus getExtensionGnssVisibilityControl(
             std::shared_ptr<android::hardware::gnss::visibility_control::IGnssVisibilityControl>*
                     iGnssVisibilityControl) override;
+    ndk::ScopedAStatus getExtensionGnssAntennaInfo(
+            std::shared_ptr<IGnssAntennaInfo>* iGnssAntennaInfo) override;
+    ndk::ScopedAStatus getExtensionMeasurementCorrections(
+            std::shared_ptr<android::hardware::gnss::measurement_corrections::
+                                    IMeasurementCorrectionsInterface>* iMeasurementCorrections)
+            override;
 
     std::shared_ptr<GnssConfiguration> mGnssConfiguration;
     std::shared_ptr<GnssPowerIndication> mGnssPowerIndication;
diff --git a/gnss/aidl/default/GnssAntennaInfo.cpp b/gnss/aidl/default/GnssAntennaInfo.cpp
new file mode 100644
index 0000000..72def71
--- /dev/null
+++ b/gnss/aidl/default/GnssAntennaInfo.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GnssAntennaInfoAidl"
+
+#include "GnssAntennaInfo.h"
+#include <aidl/android/hardware/gnss/BnGnss.h>
+#include <log/log.h>
+#include "Utils.h"
+
+namespace aidl::android::hardware::gnss {
+
+using namespace ::android::hardware::gnss;
+using Row = IGnssAntennaInfoCallback::Row;
+using Coord = IGnssAntennaInfoCallback::Coord;
+
+std::shared_ptr<IGnssAntennaInfoCallback> GnssAntennaInfo::sCallback = nullptr;
+
+GnssAntennaInfo::GnssAntennaInfo() : mMinIntervalMs(1000) {}
+
+GnssAntennaInfo::~GnssAntennaInfo() {
+    stop();
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow.
+ndk::ScopedAStatus GnssAntennaInfo::setCallback(
+        const std::shared_ptr<IGnssAntennaInfoCallback>& callback) {
+    ALOGD("setCallback");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+
+    if (mIsActive) {
+        ALOGW("GnssAntennaInfo callback already set. Resetting the callback...");
+        stop();
+    }
+    start();
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssAntennaInfo::close() {
+    ALOGD("close");
+    stop();
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = nullptr;
+    return ndk::ScopedAStatus::ok();
+}
+
+void GnssAntennaInfo::start() {
+    ALOGD("start");
+    mIsActive = true;
+    mThread = std::thread([this]() {
+        while (mIsActive == true) {
+            if (sCallback != nullptr) {
+                IGnssAntennaInfoCallback::GnssAntennaInfo mockAntennaInfo_1 = {
+                        .carrierFrequencyHz = 1575420000,
+                        .phaseCenterOffsetCoordinateMillimeters = Coord{.x = 1,
+                                                                        .xUncertainty = 0.1,
+                                                                        .y = 2,
+                                                                        .yUncertainty = 0.1,
+                                                                        .z = 3,
+                                                                        .zUncertainty = 0.1},
+                        .phaseCenterVariationCorrectionMillimeters =
+                                {
+                                        Row{std::vector<double>{1, -1, 5, -2, 3, -1}},
+                                        Row{std::vector<double>{-2, 3, 2, 0, 1, 2}},
+                                        Row{std::vector<double>{1, 3, 2, -1, -3, 5}},
+                                },
+                        .phaseCenterVariationCorrectionUncertaintyMillimeters =
+                                {
+                                        Row{std::vector<double>{0.1, 0.2, 0.4, 0.1, 0.2, 0.3}},
+                                        Row{std::vector<double>{0.3, 0.2, 0.3, 0.6, 0.1, 0.1}},
+                                        Row{std::vector<double>{0.1, 0.1, 0.4, 0.2, 0.5, 0.3}},
+                                },
+                        .signalGainCorrectionDbi =
+                                {
+                                        Row{std::vector<double>{2, -3, 1, -3, 0, -4}},
+                                        Row{std::vector<double>{1, 0, -4, 1, 3, -2}},
+                                        Row{std::vector<double>{3, -2, 0, -2, 3, 0}},
+                                },
+                        .signalGainCorrectionUncertaintyDbi =
+                                {
+                                        Row{std::vector<double>{0.3, 0.1, 0.2, 0.6, 0.1, 0.3}},
+                                        Row{std::vector<double>{0.1, 0.1, 0.5, 0.2, 0.3, 0.1}},
+                                        Row{std::vector<double>{0.2, 0.4, 0.2, 0.1, 0.1, 0.2}},
+                                },
+                };
+
+                IGnssAntennaInfoCallback::GnssAntennaInfo mockAntennaInfo_2 = {
+                        .carrierFrequencyHz = 1176450000,
+                        .phaseCenterOffsetCoordinateMillimeters = Coord{.x = 5,
+                                                                        .xUncertainty = 0.1,
+                                                                        .y = 6,
+                                                                        .yUncertainty = 0.1,
+                                                                        .z = 7,
+                                                                        .zUncertainty = 0.1},
+                };
+
+                std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo> mockAntennaInfos = {
+                        mockAntennaInfo_1,
+                        mockAntennaInfo_2,
+                };
+                this->reportAntennaInfo(mockAntennaInfos);
+            }
+
+            /** For mock implementation this is good. On real device, we should only report
+                antennaInfo at start and when there is a configuration change. **/
+            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
+        }
+    });
+}
+
+void GnssAntennaInfo::stop() {
+    ALOGD("stop");
+    mIsActive = false;
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+void GnssAntennaInfo::reportAntennaInfo(
+        const std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfo) const {
+    std::unique_lock<std::mutex> lock(mMutex);
+
+    if (sCallback == nullptr) {
+        ALOGE("%s: No non-null callback", __func__);
+        return;
+    }
+
+    auto ret = sCallback->gnssAntennaInfoCb(antennaInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssAntennaInfo.h b/gnss/aidl/default/GnssAntennaInfo.h
new file mode 100644
index 0000000..2cf7b13
--- /dev/null
+++ b/gnss/aidl/default/GnssAntennaInfo.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/gnss/BnGnssAntennaInfo.h>
+#include <atomic>
+#include <mutex>
+#include <thread>
+
+namespace aidl::android::hardware::gnss {
+
+struct GnssAntennaInfo : public BnGnssAntennaInfo {
+  public:
+    GnssAntennaInfo();
+    ~GnssAntennaInfo();
+    ndk::ScopedAStatus setCallback(
+            const std::shared_ptr<IGnssAntennaInfoCallback>& callback) override;
+    ndk::ScopedAStatus close() override;
+
+  private:
+    void start();
+    void stop();
+    void reportAntennaInfo(
+            const std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfo) const;
+
+    // Guarded by mMutex
+    static std::shared_ptr<IGnssAntennaInfoCallback> sCallback;
+
+    std::atomic<bool> mIsActive;
+    std::atomic<long> mMinIntervalMs;
+    std::thread mThread;
+
+    // Synchronization lock for sCallback
+    mutable std::mutex mMutex;
+};
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssBatching.cpp b/gnss/aidl/default/GnssBatching.cpp
index b8be5e5..33e1fd5 100644
--- a/gnss/aidl/default/GnssBatching.cpp
+++ b/gnss/aidl/default/GnssBatching.cpp
@@ -52,17 +52,19 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus GnssBatching::start(int64_t periodNanos, int flags) {
-    ALOGD("start: periodNanos=%" PRId64 ", flags=%d", periodNanos, flags);
+ndk::ScopedAStatus GnssBatching::start(const Options& options) {
+    ALOGD("start: periodNanos=%" PRId64 ", minDistanceMeters=%f, flags=%d", options.periodNanos,
+          options.minDistanceMeters, options.flags);
     if (mIsActive) {
         ALOGW("Gnss has started. Restarting...");
         stop();
     }
 
-    mWakeUpOnFifoFull = (flags & IGnssBatching::WAKEUP_ON_FIFO_FULL) ? true : false;
     // mMinIntervalMs is not smaller than 1 sec
-    periodNanos = (periodNanos < 1e9) ? 1e9 : periodNanos;
+    long periodNanos = (options.periodNanos < 1e9) ? 1e9 : options.periodNanos;
     mMinIntervalMs = periodNanos / 1e6;
+    mWakeUpOnFifoFull = (options.flags & IGnssBatching::WAKEUP_ON_FIFO_FULL) ? true : false;
+    mMinDistanceMeters = options.minDistanceMeters;
 
     mIsActive = true;
     mThread = std::thread([this]() {
diff --git a/gnss/aidl/default/GnssBatching.h b/gnss/aidl/default/GnssBatching.h
index 7cd6e85..6d1d809 100644
--- a/gnss/aidl/default/GnssBatching.h
+++ b/gnss/aidl/default/GnssBatching.h
@@ -28,7 +28,7 @@
     ~GnssBatching();
     ndk::ScopedAStatus init(const std::shared_ptr<IGnssBatchingCallback>& callback) override;
     ndk::ScopedAStatus getBatchSize(int* size) override;
-    ndk::ScopedAStatus start(int64_t periodNanos, int flags) override;
+    ndk::ScopedAStatus start(const Options& options) override;
     ndk::ScopedAStatus flush() override;
     ndk::ScopedAStatus stop() override;
     ndk::ScopedAStatus cleanup() override;
@@ -42,6 +42,7 @@
     std::thread mThread;
     std::atomic<bool> mIsActive;
     std::atomic<long> mMinIntervalMs;
+    std::atomic<float> mMinDistanceMeters;
     std::atomic<bool> mWakeUpOnFifoFull;
 
     // Synchronization lock for sCallback
diff --git a/gnss/aidl/default/MeasurementCorrectionsInterface.cpp b/gnss/aidl/default/MeasurementCorrectionsInterface.cpp
new file mode 100644
index 0000000..0f1851c
--- /dev/null
+++ b/gnss/aidl/default/MeasurementCorrectionsInterface.cpp
@@ -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.
+ */
+
+#define LOG_TAG "MeasurementCorrectionsInterface"
+
+#include "MeasurementCorrectionsInterface.h"
+#include <inttypes.h>
+#include <log/log.h>
+
+namespace aidl::android::hardware::gnss::measurement_corrections {
+
+std::shared_ptr<IMeasurementCorrectionsCallback> MeasurementCorrectionsInterface::sCallback =
+        nullptr;
+
+ndk::ScopedAStatus MeasurementCorrectionsInterface::setCorrections(
+        const MeasurementCorrections& corrections) {
+    ALOGD("setCorrections");
+    ALOGD("corrections = lat: %f, lng: %f, alt: %f, hUnc: %f, vUnc: %f, toa: %llu, "
+          "satCorrections.size: %d",
+          corrections.latitudeDegrees, corrections.longitudeDegrees, corrections.altitudeMeters,
+          corrections.horizontalPositionUncertaintyMeters,
+          corrections.verticalPositionUncertaintyMeters,
+          static_cast<unsigned long long>(corrections.toaGpsNanosecondsOfWeek),
+          static_cast<int>(corrections.satCorrections.size()));
+    for (auto singleSatCorrection : corrections.satCorrections) {
+        ALOGD("singleSatCorrection = flags: %d, constellation: %d, svid: %d"
+              ", cfHz: %" PRId64 ", probLos: %f, epl: %f, eplUnc: %f",
+              singleSatCorrection.singleSatCorrectionFlags, singleSatCorrection.constellation,
+              singleSatCorrection.svid, singleSatCorrection.carrierFrequencyHz,
+              singleSatCorrection.probSatIsLos, singleSatCorrection.excessPathLengthMeters,
+              singleSatCorrection.excessPathLengthUncertaintyMeters);
+        ALOGD("reflecting plane = lat: %f, lng: %f, alt: %f, azm: %f",
+              singleSatCorrection.reflectingPlane.latitudeDegrees,
+              singleSatCorrection.reflectingPlane.longitudeDegrees,
+              singleSatCorrection.reflectingPlane.altitudeMeters,
+              singleSatCorrection.reflectingPlane.azimuthDegrees);
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus MeasurementCorrectionsInterface::setCallback(
+        const std::shared_ptr<IMeasurementCorrectionsCallback>& callback) {
+    ALOGD("MeasurementCorrections::setCallback");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+    auto ret = sCallback->setCapabilitiesCb(
+            IMeasurementCorrectionsCallback::CAPABILITY_LOS_SATS |
+            IMeasurementCorrectionsCallback::CAPABILITY_EXCESS_PATH_LENGTH |
+            IMeasurementCorrectionsCallback::CAPABILITY_REFLECTING_PLANE);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    return ndk::ScopedAStatus::ok();
+}
+}  // namespace aidl::android::hardware::gnss::measurement_corrections
diff --git a/gnss/aidl/default/MeasurementCorrectionsInterface.h b/gnss/aidl/default/MeasurementCorrectionsInterface.h
new file mode 100644
index 0000000..af58725
--- /dev/null
+++ b/gnss/aidl/default/MeasurementCorrectionsInterface.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/gnss/measurement_corrections/BnMeasurementCorrectionsInterface.h>
+
+namespace aidl::android::hardware::gnss::measurement_corrections {
+
+struct MeasurementCorrectionsInterface : public BnMeasurementCorrectionsInterface {
+  public:
+    ndk::ScopedAStatus setCorrections(const MeasurementCorrections& corrections) override;
+    ndk::ScopedAStatus setCallback(
+            const std::shared_ptr<IMeasurementCorrectionsCallback>& callback) override;
+
+  private:
+    // Synchronization lock for sCallback
+    mutable std::mutex mMutex;
+    // Guarded by mMutex
+    static std::shared_ptr<IMeasurementCorrectionsCallback> sCallback;
+};
+
+}  // namespace aidl::android::hardware::gnss::measurement_corrections
diff --git a/gnss/aidl/vts/AGnssRilCallbackAidl.cpp b/gnss/aidl/vts/AGnssRilCallbackAidl.cpp
new file mode 100644
index 0000000..4e4166d
--- /dev/null
+++ b/gnss/aidl/vts/AGnssRilCallbackAidl.cpp
@@ -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.
+ */
+
+#include "AGnssRilCallbackAidl.h"
+#include <log/log.h>
+
+android::binder::Status AGnssRilCallbackAidl::requestSetIdCb(int setIdflag) {
+    ALOGI("requestSetIdCb setIdflag %d", setIdflag);
+    return android::binder::Status::ok();
+}
+
+android::binder::Status AGnssRilCallbackAidl::requestRefLocCb() {
+    ALOGI("requestRefLocCb");
+    return android::binder::Status::ok();
+}
diff --git a/gnss/aidl/vts/AGnssRilCallbackAidl.h b/gnss/aidl/vts/AGnssRilCallbackAidl.h
new file mode 100644
index 0000000..74b34ee
--- /dev/null
+++ b/gnss/aidl/vts/AGnssRilCallbackAidl.h
@@ -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.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/BnAGnssRilCallback.h>
+
+/** Implementation for IAGnssRilCallback. */
+class AGnssRilCallbackAidl : public android::hardware::gnss::BnAGnssRilCallback {
+  public:
+    AGnssRilCallbackAidl(){};
+    ~AGnssRilCallbackAidl(){};
+    android::binder::Status requestSetIdCb(int setIdflag) override;
+    android::binder::Status requestRefLocCb() override;
+};
diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp
index d532fad..f02a41e 100644
--- a/gnss/aidl/vts/Android.bp
+++ b/gnss/aidl/vts/Android.bp
@@ -31,6 +31,8 @@
         "gnss_hal_test.cpp",
         "gnss_hal_test_cases.cpp",
         "AGnssCallbackAidl.cpp",
+        "AGnssRilCallbackAidl.cpp",
+        "GnssAntennaInfoCallbackAidl.cpp",
         "GnssBatchingCallback.cpp",
         "GnssCallbackAidl.cpp",
         "GnssGeofenceCallback.cpp",
@@ -38,6 +40,7 @@
         "GnssNavigationMessageCallback.cpp",
         "GnssPowerIndicationCallback.cpp",
         "GnssVisibilityControlCallback.cpp",
+        "MeasurementCorrectionsCallback.cpp",
         "VtsHalGnssTargetTest.cpp",
     ],
     shared_libs: [
@@ -50,7 +53,6 @@
     static_libs: [
         "android.hardware.gnss-V2-cpp",
         "android.hardware.gnss@common-vts-lib",
-        "android.hardware.gnss.visibility_control-V1-cpp",
     ],
     test_suites: [
         "general-tests",
diff --git a/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.cpp b/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.cpp
new file mode 100644
index 0000000..11001cd
--- /dev/null
+++ b/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.cpp
@@ -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.
+ */
+
+#include "GnssAntennaInfoCallbackAidl.h"
+#include <inttypes.h>
+#include <log/log.h>
+
+android::binder::Status GnssAntennaInfoCallbackAidl::gnssAntennaInfoCb(
+        const std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos) {
+    ALOGD("GnssAntennaInfo received. Size = %d", (int)gnssAntennaInfos.size());
+    antenna_info_cbq_.store(gnssAntennaInfos);
+    return android::binder::Status::ok();
+}
diff --git a/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.h b/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.h
new file mode 100644
index 0000000..77e1057
--- /dev/null
+++ b/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.h
@@ -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.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/BnGnssAntennaInfoCallback.h>
+#include <vector>
+#include "GnssCallbackEventQueue.h"
+
+/** Implementation for IGnssAntennaInfoCallback. */
+class GnssAntennaInfoCallbackAidl : public android::hardware::gnss::BnGnssAntennaInfoCallback {
+  public:
+    GnssAntennaInfoCallbackAidl() : antenna_info_cbq_("info"){};
+    ~GnssAntennaInfoCallbackAidl(){};
+
+    android::binder::Status gnssAntennaInfoCb(
+            const std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos)
+            override;
+
+    android::hardware::gnss::common::GnssCallbackEventQueue<
+            std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo>>
+            antenna_info_cbq_;
+};
diff --git a/gnss/aidl/vts/MeasurementCorrectionsCallback.cpp b/gnss/aidl/vts/MeasurementCorrectionsCallback.cpp
new file mode 100644
index 0000000..db1f7a6
--- /dev/null
+++ b/gnss/aidl/vts/MeasurementCorrectionsCallback.cpp
@@ -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.
+ */
+
+#define LOG_TAG "MeasurementCorrectionsCallback"
+
+#include "MeasurementCorrectionsCallback.h"
+#include <log/log.h>
+
+android::binder::Status MeasurementCorrectionsCallback::setCapabilitiesCb(const int capabilities) {
+    ALOGI("Capabilities received %d", capabilities);
+    capabilities_cbq_.store(capabilities);
+    return android::binder::Status::ok();
+}
diff --git a/gnss/aidl/vts/MeasurementCorrectionsCallback.h b/gnss/aidl/vts/MeasurementCorrectionsCallback.h
new file mode 100644
index 0000000..27e5b3c
--- /dev/null
+++ b/gnss/aidl/vts/MeasurementCorrectionsCallback.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 <android/hardware/gnss/measurement_corrections/BnMeasurementCorrectionsCallback.h>
+#include "GnssCallbackEventQueue.h"
+
+class MeasurementCorrectionsCallback
+    : public android::hardware::gnss::measurement_corrections::BnMeasurementCorrectionsCallback {
+  public:
+    MeasurementCorrectionsCallback() : capabilities_cbq_("capabilities"){};
+    ~MeasurementCorrectionsCallback(){};
+    android::binder::Status setCapabilitiesCb(const int capabilities) override;
+
+    android::hardware::gnss::common::GnssCallbackEventQueue<int> capabilities_cbq_;
+    int last_capabilities_;
+};
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 9acef8b..1fa6825 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -18,21 +18,27 @@
 
 #include <android/hardware/gnss/IAGnss.h>
 #include <android/hardware/gnss/IGnss.h>
+#include <android/hardware/gnss/IGnssAntennaInfo.h>
 #include <android/hardware/gnss/IGnssBatching.h>
 #include <android/hardware/gnss/IGnssDebug.h>
 #include <android/hardware/gnss/IGnssMeasurementCallback.h>
 #include <android/hardware/gnss/IGnssMeasurementInterface.h>
 #include <android/hardware/gnss/IGnssPowerIndication.h>
 #include <android/hardware/gnss/IGnssPsds.h>
+#include <android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsInterface.h>
 #include <android/hardware/gnss/visibility_control/IGnssVisibilityControl.h>
 #include <cutils/properties.h>
 #include "AGnssCallbackAidl.h"
+#include "AGnssRilCallbackAidl.h"
+#include "GnssAntennaInfoCallbackAidl.h"
 #include "GnssBatchingCallback.h"
 #include "GnssGeofenceCallback.h"
 #include "GnssMeasurementCallbackAidl.h"
 #include "GnssNavigationMessageCallback.h"
 #include "GnssPowerIndicationCallback.h"
 #include "GnssVisibilityControlCallback.h"
+#include "MeasurementCorrectionsCallback.h"
+#include "Utils.h"
 #include "gnss_hal_test.h"
 
 using android::sp;
@@ -43,7 +49,10 @@
 using android::hardware::gnss::GnssMeasurement;
 using android::hardware::gnss::GnssPowerStats;
 using android::hardware::gnss::IAGnss;
+using android::hardware::gnss::IAGnssRil;
 using android::hardware::gnss::IGnss;
+using android::hardware::gnss::IGnssAntennaInfo;
+using android::hardware::gnss::IGnssAntennaInfoCallback;
 using android::hardware::gnss::IGnssBatching;
 using android::hardware::gnss::IGnssBatchingCallback;
 using android::hardware::gnss::IGnssCallback;
@@ -58,6 +67,8 @@
 using android::hardware::gnss::IGnssPsds;
 using android::hardware::gnss::PsdsType;
 using android::hardware::gnss::SatellitePvt;
+using android::hardware::gnss::common::Utils;
+using android::hardware::gnss::measurement_corrections::IMeasurementCorrectionsInterface;
 using android::hardware::gnss::visibility_control::IGnssVisibilityControl;
 
 using GnssConstellationTypeV2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
@@ -802,6 +813,10 @@
  * TestAllExtensions.
  */
 TEST_P(GnssHalTest, TestAllExtensions) {
+    if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+        return;
+    }
+
     sp<IGnssBatching> iGnssBatching;
     auto status = aidl_gnss_hal_->getExtensionGnssBatching(&iGnssBatching);
     if (status.isOk() && iGnssBatching != nullptr) {
@@ -858,6 +873,42 @@
 }
 
 /*
+ * TestAGnssRilExtension:
+ * 1. Gets the IAGnssRil extension.
+ * 2. Sets AGnssRilCallback.
+ * 3. Sets reference location.
+ */
+TEST_P(GnssHalTest, TestAGnssRilExtension) {
+    if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+        return;
+    }
+    sp<IAGnssRil> iAGnssRil;
+    auto status = aidl_gnss_hal_->getExtensionAGnssRil(&iAGnssRil);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(iAGnssRil != nullptr);
+
+    auto agnssRilCallback = sp<AGnssRilCallbackAidl>::make();
+    status = iAGnssRil->setCallback(agnssRilCallback);
+    ASSERT_TRUE(status.isOk());
+
+    // Set RefLocation
+    IAGnssRil::AGnssRefLocationCellID agnssReflocationCellId;
+    agnssReflocationCellId.type = IAGnssRil::AGnssRefLocationType::LTE_CELLID;
+    agnssReflocationCellId.mcc = 466;
+    agnssReflocationCellId.mnc = 97;
+    agnssReflocationCellId.lac = 46697;
+    agnssReflocationCellId.cid = 59168142;
+    agnssReflocationCellId.pcid = 420;
+    agnssReflocationCellId.tac = 11460;
+    IAGnssRil::AGnssRefLocation agnssReflocation;
+    agnssReflocation.type = IAGnssRil::AGnssRefLocationType::LTE_CELLID;
+    agnssReflocation.cellID = agnssReflocationCellId;
+
+    status = iAGnssRil->setRefLocation(agnssReflocation);
+    ASSERT_TRUE(status.isOk());
+}
+
+/*
  * GnssDebugValuesSanityTest:
  * Ensures that GnssDebug values make sense.
  */
@@ -905,7 +956,6 @@
 }
 
 /*
- * TestAGnssExtension:
  * TestGnssVisibilityControlExtension:
  * 1. Gets the IGnssVisibilityControl extension.
  * 2. Sets GnssVisibilityControlCallback
@@ -923,7 +973,8 @@
     status = iGnssVisibilityControl->setCallback(gnssVisibilityControlCallback);
     ASSERT_TRUE(status.isOk());
 
-    std::vector<String16> proxyApps{String16("com.example.ims"), String16("com.example.mdt")};
+    std::vector<std::string> proxyApps{std::string("com.example.ims"),
+                                       std::string("com.example.mdt")};
     status = iGnssVisibilityControl->enableNfwLocationAccess(proxyApps);
     ASSERT_TRUE(status.isOk());
 }
@@ -966,3 +1017,167 @@
     status = iGnssMeasurement->close();
     ASSERT_TRUE(status.isOk());
 }
+
+/*
+ * TestGnssAgcInGnssMeasurement:
+ * 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension.
+ * 2. Sets a GnssMeasurementCallback, waits for a measurement.
+ */
+TEST_P(GnssHalTest, TestGnssAgcInGnssMeasurement) {
+    if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+        return;
+    }
+    const int kFirstGnssMeasurementTimeoutSeconds = 10;
+    const int kNumMeasurementEvents = 15;
+
+    sp<IGnssMeasurementInterface> iGnssMeasurement;
+    auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(iGnssMeasurement != nullptr);
+
+    auto callback = sp<GnssMeasurementCallbackAidl>::make();
+    status = iGnssMeasurement->setCallback(callback, /* enableFullTracking= */ false,
+                                           /* enableCorrVecOutputs */ false);
+    ASSERT_TRUE(status.isOk());
+
+    for (int i = 0; i < kNumMeasurementEvents; i++) {
+        GnssData lastMeasurement;
+        ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement,
+                                                      kFirstGnssMeasurementTimeoutSeconds));
+        EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
+        ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
+
+        // Validity check GnssData fields
+        CheckGnssMeasurementClockFields(lastMeasurement);
+
+        ASSERT_TRUE(lastMeasurement.gnssAgcs.has_value());
+        for (const auto& gnssAgc : lastMeasurement.gnssAgcs.value()) {
+            ASSERT_TRUE(gnssAgc.has_value());
+            ASSERT_TRUE(gnssAgc.value().carrierFrequencyHz >= 0);
+        }
+    }
+
+    status = iGnssMeasurement->close();
+    ASSERT_TRUE(status.isOk());
+}
+
+/*
+ * TestGnssAntennaInfo:
+ * Sets a GnssAntennaInfoCallback, waits for report, and verifies
+ * 1. phaseCenterOffsetCoordinateMillimeters is valid
+ * 2. phaseCenterOffsetCoordinateUncertaintyMillimeters is valid.
+ * PhaseCenterVariationCorrections and SignalGainCorrections are optional.
+ */
+TEST_P(GnssHalTest, TestGnssAntennaInfo) {
+    const int kAntennaInfoTimeoutSeconds = 2;
+
+    if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+        return;
+    }
+
+    sp<IGnssAntennaInfo> iGnssAntennaInfo;
+    auto status = aidl_gnss_hal_->getExtensionGnssAntennaInfo(&iGnssAntennaInfo);
+    ASSERT_TRUE(status.isOk());
+
+    if (!(aidl_gnss_cb_->last_capabilities_ & (int)GnssCallbackAidl::CAPABILITY_ANTENNA_INFO) ||
+        iGnssAntennaInfo == nullptr) {
+        ALOGD("GnssAntennaInfo AIDL is not supported.");
+        return;
+    }
+
+    auto callback = sp<GnssAntennaInfoCallbackAidl>::make();
+    status = iGnssAntennaInfo->setCallback(callback);
+    ASSERT_TRUE(status.isOk());
+
+    std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo> antennaInfos;
+    ASSERT_TRUE(callback->antenna_info_cbq_.retrieve(antennaInfos, kAntennaInfoTimeoutSeconds));
+    EXPECT_EQ(callback->antenna_info_cbq_.calledCount(), 1);
+    ASSERT_TRUE(antennaInfos.size() > 0);
+
+    for (auto antennaInfo : antennaInfos) {
+        // Remaining fields are optional
+        if (!antennaInfo.phaseCenterVariationCorrectionMillimeters.empty()) {
+            int numRows = antennaInfo.phaseCenterVariationCorrectionMillimeters.size();
+            int numColumns = antennaInfo.phaseCenterVariationCorrectionMillimeters[0].row.size();
+            // Must have at least 1 row and 2 columns
+            ASSERT_TRUE(numRows >= 1 && numColumns >= 2);
+
+            // Corrections and uncertainties must have same dimensions
+            ASSERT_TRUE(antennaInfo.phaseCenterVariationCorrectionMillimeters.size() ==
+                        antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.size());
+            ASSERT_TRUE(
+                    antennaInfo.phaseCenterVariationCorrectionMillimeters[0].row.size() ==
+                    antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters[0].row.size());
+
+            // Must be rectangular
+            for (auto row : antennaInfo.phaseCenterVariationCorrectionMillimeters) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+            for (auto row : antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+        }
+        if (!antennaInfo.signalGainCorrectionDbi.empty()) {
+            int numRows = antennaInfo.signalGainCorrectionDbi.size();
+            int numColumns = antennaInfo.signalGainCorrectionUncertaintyDbi[0].row.size();
+            // Must have at least 1 row and 2 columns
+            ASSERT_TRUE(numRows >= 1 && numColumns >= 2);
+
+            // Corrections and uncertainties must have same dimensions
+            ASSERT_TRUE(antennaInfo.signalGainCorrectionDbi.size() ==
+                        antennaInfo.signalGainCorrectionUncertaintyDbi.size());
+            ASSERT_TRUE(antennaInfo.signalGainCorrectionDbi[0].row.size() ==
+                        antennaInfo.signalGainCorrectionUncertaintyDbi[0].row.size());
+
+            // Must be rectangular
+            for (auto row : antennaInfo.signalGainCorrectionDbi) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+            for (auto row : antennaInfo.signalGainCorrectionUncertaintyDbi) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+        }
+    }
+
+    iGnssAntennaInfo->close();
+}
+
+/*
+ * TestGnssMeasurementCorrections:
+ * If measurement corrections capability is supported, verifies that the measurement corrections
+ * capabilities are reported and the mandatory LOS_SATS or the EXCESS_PATH_LENGTH
+ * capability flag is set.
+ */
+TEST_P(GnssHalTest, TestGnssMeasurementCorrections) {
+    if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+        return;
+    }
+    if (!(aidl_gnss_cb_->last_capabilities_ &
+          (int)GnssCallbackAidl::CAPABILITY_MEASUREMENT_CORRECTIONS)) {
+        return;
+    }
+
+    sp<IMeasurementCorrectionsInterface> iMeasurementCorrectionsAidl;
+    auto status = aidl_gnss_hal_->getExtensionMeasurementCorrections(&iMeasurementCorrectionsAidl);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(iMeasurementCorrectionsAidl != nullptr);
+
+    // Setup measurement corrections callback.
+    auto gnssMeasurementCorrectionsCallback = sp<MeasurementCorrectionsCallback>::make();
+    status = iMeasurementCorrectionsAidl->setCallback(gnssMeasurementCorrectionsCallback);
+    ASSERT_TRUE(status.isOk());
+
+    const int kTimeoutSec = 5;
+    EXPECT_TRUE(gnssMeasurementCorrectionsCallback->capabilities_cbq_.retrieve(
+            gnssMeasurementCorrectionsCallback->last_capabilities_, kTimeoutSec));
+    ASSERT_TRUE(gnssMeasurementCorrectionsCallback->capabilities_cbq_.calledCount() > 0);
+
+    ASSERT_TRUE((gnssMeasurementCorrectionsCallback->last_capabilities_ &
+                 (MeasurementCorrectionsCallback::CAPABILITY_LOS_SATS |
+                  MeasurementCorrectionsCallback::CAPABILITY_EXCESS_PATH_LENGTH)) != 0);
+
+    // Set a mock MeasurementCorrections.
+    status = iMeasurementCorrectionsAidl->setCorrections(
+            Utils::getMockMeasurementCorrections_aidl());
+    ASSERT_TRUE(status.isOk());
+}
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index 05bec88..b896f04 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -39,6 +39,7 @@
         "v2_1/GnssMeasurement.cpp",
         "v2_1/GnssMeasurementCorrections.cpp",
         "DeviceFileReader.cpp",
+        "FixLocationParser.cpp",
         "GnssRawMeasurementParser.cpp",
         "GnssReplayUtils.cpp",
         "MockLocation.cpp",
diff --git a/gnss/common/utils/default/FixLocationParser.cpp b/gnss/common/utils/default/FixLocationParser.cpp
new file mode 100644
index 0000000..f391d96
--- /dev/null
+++ b/gnss/common/utils/default/FixLocationParser.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FixLocationParser.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+using aidl::android::hardware::gnss::ElapsedRealtime;
+using aidl::android::hardware::gnss::GnssLocation;
+
+std::unique_ptr<GnssLocation> FixLocationParser::getLocationFromInputStr(
+        const std::string& locationStr) {
+    /*
+     * Fix,Provider,LatitudeDegrees,LongitudeDegrees,AltitudeMeters,SpeedMps,
+     * AccuracyMeters,BearingDegrees,UnixTimeMillis,SpeedAccuracyMps,BearingAccuracyDegrees,
+     * elapsedRealtimeNanos
+     */
+    if (locationStr.empty()) {
+        return nullptr;
+    }
+    std::vector<std::string> locationStrRecords;
+    ParseUtils::splitStr(locationStr, LINE_SEPARATOR, locationStrRecords);
+    if (locationStrRecords.empty()) {
+        return nullptr;
+    }
+
+    std::vector<std::string> locationValues;
+    ParseUtils::splitStr(locationStrRecords[0], COMMA_SEPARATOR, locationValues);
+    if (locationValues.size() < 12) {
+        return nullptr;
+    }
+    ElapsedRealtime elapsedRealtime = {
+            .flags = ElapsedRealtime::HAS_TIMESTAMP_NS | ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS,
+            .timestampNs = ::android::elapsedRealtimeNano(),
+            // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
+            // In an actual implementation provide an estimate of the synchronization uncertainty
+            // or don't set the field.
+            .timeUncertaintyNs = 1020400};
+
+    GnssLocation location = {
+            .gnssLocationFlags = 0xFF,
+            .latitudeDegrees = ParseUtils::tryParseDouble(locationValues[2], 0),
+            .longitudeDegrees = ParseUtils::tryParseDouble(locationValues[3], 0),
+            .altitudeMeters = ParseUtils::tryParseDouble(locationValues[4], 0),
+            .speedMetersPerSec = ParseUtils::tryParseDouble(locationValues[5], 0),
+            .bearingDegrees = ParseUtils::tryParseDouble(locationValues[7], 0),
+            .horizontalAccuracyMeters = ParseUtils::tryParseDouble(locationValues[6], 0),
+            .verticalAccuracyMeters = ParseUtils::tryParseDouble(locationValues[6], 0),
+            .speedAccuracyMetersPerSecond = ParseUtils::tryParseDouble(locationValues[9], 0),
+            .bearingAccuracyDegrees = ParseUtils::tryParseDouble(locationValues[10], 0),
+            .timestampMillis = ParseUtils::tryParseLongLong(locationValues[8], 0),
+            .elapsedRealtime = elapsedRealtime};
+    return std::make_unique<GnssLocation>(location);
+}
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index 563c6d5..1ff84eb 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -38,6 +38,7 @@
 using GnssSvFlags = aidl::android::hardware::gnss::IGnssCallback::GnssSvFlags;
 
 using GnssSvFlagsV1_0 = V1_0::IGnssCallback::GnssSvFlags;
+using GnssAgc = aidl::android::hardware::gnss::GnssData::GnssAgc;
 using GnssMeasurementFlagsV1_0 = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags;
 using GnssMeasurementFlagsV2_1 = V2_1::IGnssMeasurementCallback::GnssMeasurementFlags;
 using GnssMeasurementStateV2_0 = V2_0::IGnssMeasurementCallback::GnssMeasurementState;
@@ -231,8 +232,23 @@
         measurement.flags |= GnssMeasurement::HAS_CORRELATION_VECTOR;
     }
 
-    GnssData gnssData = {
-            .measurements = {measurement}, .clock = clock, .elapsedRealtime = timestamp};
+    GnssAgc gnssAgc1 = {
+            .agcLevelDb = 3.5,
+            .constellation = GnssConstellationType::GLONASS,
+            .carrierFrequencyHz = (int64_t)kGloG1FreqHz,
+    };
+
+    GnssAgc gnssAgc2 = {
+            .agcLevelDb = -5.1,
+            .constellation = GnssConstellationType::GPS,
+            .carrierFrequencyHz = (int64_t)kGpsL1FreqHz,
+    };
+
+    GnssData gnssData = {.measurements = {measurement},
+                         .clock = clock,
+                         .elapsedRealtime = timestamp,
+                         .gnssAgcs = std::make_optional(std::vector(
+                                 {std::make_optional(gnssAgc1), std::make_optional(gnssAgc2)}))};
     return gnssData;
 }
 
diff --git a/gnss/common/utils/default/include/FixLocationParser.h b/gnss/common/utils/default/include/FixLocationParser.h
new file mode 100644
index 0000000..a738914
--- /dev/null
+++ b/gnss/common/utils/default/include/FixLocationParser.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_common_default_FixLocationParser_H_
+#define android_hardware_gnss_common_default_FixLocationParser_H_
+
+#include <aidl/android/hardware/gnss/BnGnss.h>
+
+#include <utils/SystemClock.h>
+#include <string>
+#include <vector>
+
+#include <Constants.h>
+#include <Utils.h>
+#include <log/log.h>
+#include "Constants.h"
+#include "ParseUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct FixLocationParser {
+  public:
+    static std::unique_ptr<aidl::android::hardware::gnss::GnssLocation> getLocationFromInputStr(
+            const std::string& inputStr);
+};
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_common_default_FixLocationParser_H_
\ No newline at end of file
diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp
index 06bce9d..da4c07f 100644
--- a/gnss/common/utils/vts/Utils.cpp
+++ b/gnss/common/utils/vts/Utils.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <Utils.h>
+#include <android/hardware/gnss/BnGnss.h>
 #include <android/hardware/gnss/IGnss.h>
 #include "gtest/gtest.h"
 
@@ -28,6 +29,12 @@
 using namespace measurement_corrections::V1_0;
 using V1_0::GnssLocationFlags;
 
+using MeasurementCorrectionsAidl =
+        android::hardware::gnss::measurement_corrections::MeasurementCorrections;
+using ReflectingPlaneAidl = android::hardware::gnss::measurement_corrections::ReflectingPlane;
+using SingleSatCorrectionAidl =
+        android::hardware::gnss::measurement_corrections::SingleSatCorrection;
+
 template <>
 int64_t Utils::getLocationTimestampMillis(const android::hardware::gnss::GnssLocation& location) {
     return location.timestampMillis;
@@ -63,6 +70,7 @@
             .singleSatCorrectionFlags = GnssSingleSatCorrectionFlags::HAS_SAT_IS_LOS_PROBABILITY |
                                         GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH |
                                         GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH_UNC,
+
             .constellation = V1_0::GnssConstellationType::GPS,
             .svid = 9,
             .carrierFrequencyHz = 1.59975e+09,
@@ -114,6 +122,56 @@
     return mockCorrections_1_1;
 }
 
+const MeasurementCorrectionsAidl Utils::getMockMeasurementCorrections_aidl() {
+    ReflectingPlaneAidl reflectingPlane;
+    reflectingPlane.latitudeDegrees = 37.4220039;
+    reflectingPlane.longitudeDegrees = -122.0840991;
+    reflectingPlane.altitudeMeters = 250.35;
+    reflectingPlane.azimuthDegrees = 203.0;
+
+    SingleSatCorrectionAidl singleSatCorrection1;
+    singleSatCorrection1.singleSatCorrectionFlags =
+            SingleSatCorrectionAidl::SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY |
+            SingleSatCorrectionAidl::SINGLE_SAT_CORRECTION_HAS_EXCESS_PATH_LENGTH |
+            SingleSatCorrectionAidl::SINGLE_SAT_CORRECTION_HAS_EXCESS_PATH_LENGTH_UNC |
+            SingleSatCorrectionAidl::SINGLE_SAT_CORRECTION_HAS_REFLECTING_PLANE;
+    singleSatCorrection1.constellation = android::hardware::gnss::GnssConstellationType::GPS;
+    singleSatCorrection1.svid = 12;
+    singleSatCorrection1.carrierFrequencyHz = 1.59975e+09;
+    singleSatCorrection1.probSatIsLos = 0.50001;
+    singleSatCorrection1.excessPathLengthMeters = 137.4802;
+    singleSatCorrection1.excessPathLengthUncertaintyMeters = 25.5;
+    singleSatCorrection1.reflectingPlane = reflectingPlane;
+
+    SingleSatCorrectionAidl singleSatCorrection2;
+    singleSatCorrection2.singleSatCorrectionFlags =
+            SingleSatCorrectionAidl::SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY |
+            SingleSatCorrectionAidl::SINGLE_SAT_CORRECTION_HAS_EXCESS_PATH_LENGTH |
+            SingleSatCorrectionAidl::SINGLE_SAT_CORRECTION_HAS_EXCESS_PATH_LENGTH_UNC;
+    singleSatCorrection2.constellation = GnssConstellationType::GPS;
+    singleSatCorrection2.svid = 9;
+    singleSatCorrection2.carrierFrequencyHz = 1.59975e+09;
+    singleSatCorrection2.probSatIsLos = 0.873;
+    singleSatCorrection2.excessPathLengthMeters = 26.294;
+    singleSatCorrection2.excessPathLengthUncertaintyMeters = 10.0;
+
+    std::vector<SingleSatCorrectionAidl> singleSatCorrections = {singleSatCorrection1,
+                                                                 singleSatCorrection2};
+    MeasurementCorrectionsAidl mockCorrections;
+    mockCorrections.latitudeDegrees = 37.4219999;
+    mockCorrections.longitudeDegrees = -122.0840575;
+    mockCorrections.altitudeMeters = 30.60062531;
+    mockCorrections.horizontalPositionUncertaintyMeters = 9.23542;
+    mockCorrections.verticalPositionUncertaintyMeters = 15.02341;
+    mockCorrections.toaGpsNanosecondsOfWeek = 2935633453L;
+    mockCorrections.hasEnvironmentBearing = true;
+    mockCorrections.environmentBearingDegrees = 45.0;
+    mockCorrections.environmentBearingUncertaintyDegrees = 4.0;
+    mockCorrections.satCorrections = singleSatCorrections;
+
+    return mockCorrections;
+}
+
 /*
  * MapConstellationType:
  * Given a GnssConstellationType_2_0 type constellation, maps to its equivalent
diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h
index 40f31d2..4ea6cd6 100644
--- a/gnss/common/utils/vts/include/Utils.h
+++ b/gnss/common/utils/vts/include/Utils.h
@@ -21,6 +21,8 @@
 #include <android/hardware/gnss/2.0/IGnss.h>
 #include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
 #include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
+#include <android/hardware/gnss/measurement_corrections/BnMeasurementCorrectionsInterface.h>
+
 #include <gtest/gtest.h>
 
 namespace android {
@@ -36,6 +38,8 @@
     getMockMeasurementCorrections();
     static const measurement_corrections::V1_1::MeasurementCorrections
     getMockMeasurementCorrections_1_1();
+    static const android::hardware::gnss::measurement_corrections::MeasurementCorrections
+    getMockMeasurementCorrections_aidl();
 
     static V1_0::GnssConstellationType mapConstellationType(
             V2_0::GnssConstellationType constellation);
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl
index 5c3d4cb..359c655 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl
@@ -34,6 +34,7 @@
 package android.hardware.graphics.common;
 @Backing(type="int") @VintfStability
 enum Transform {
+  NONE = 0,
   FLIP_H = 1,
   FLIP_V = 2,
   ROT_90 = 4,
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Transform.aidl b/graphics/common/aidl/android/hardware/graphics/common/Transform.aidl
index 325816c..4b3a1b1 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/Transform.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/Transform.aidl
@@ -23,6 +23,11 @@
 @Backing(type="int")
 enum Transform {
     /**
+     * Identity transform (i.e. no rotation or flip).
+     */
+    NONE = 0,
+
+    /**
      * Horizontal flip. FLIP_H/FLIP_V is applied before ROT_90.
      */
     FLIP_H = 1 << 0,
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/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/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/OWNERS b/graphics/composer/2.1/vts/functional/OWNERS
index a2ed8c8..3d970d1 100644
--- a/graphics/composer/2.1/vts/functional/OWNERS
+++ b/graphics/composer/2.1/vts/functional/OWNERS
@@ -1,2 +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/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/utils/vts/ReadbackVts.cpp b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
index 30596fc..a1794af 100644
--- a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
@@ -17,6 +17,7 @@
 #include <composer-vts/2.2/ReadbackVts.h>
 #include <composer-vts/2.2/RenderEngineVts.h>
 #include "renderengine/ExternalTexture.h"
+#include "renderengine/impl/ExternalTexture.h"
 
 namespace android {
 namespace hardware {
@@ -281,11 +282,11 @@
 
 LayerSettings TestBufferLayer::toRenderEngineLayerSettings() {
     LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
-    layerSettings.source.buffer.buffer = std::make_shared<renderengine::ExternalTexture>(
+    layerSettings.source.buffer.buffer = std::make_shared<renderengine::impl::ExternalTexture>(
             new GraphicBuffer(mBufferHandle->get(), GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
                               static_cast<int32_t>(mFormat), 1, mUsage, mStride),
             mRenderEngine.getInternalRenderEngine(),
-            renderengine::ExternalTexture::Usage::READABLE);
+            renderengine::impl::ExternalTexture::Usage::READABLE);
 
     layerSettings.source.buffer.usePremultipliedAlpha =
             mBlendMode == IComposerClient::BlendMode::PREMULTIPLIED;
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
index 2d4cc7d..4a33fb5 100644
--- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <composer-vts/2.2/RenderEngineVts.h>
+#include "renderengine/impl/ExternalTexture.h"
 
 namespace android {
 namespace hardware {
@@ -68,8 +69,8 @@
                    [](renderengine::LayerSettings& settings) -> renderengine::LayerSettings {
                        return settings;
                    });
-    auto texture = std::make_shared<renderengine::ExternalTexture>(
-            mGraphicBuffer, *mRenderEngine, renderengine::ExternalTexture::Usage::WRITEABLE);
+    auto texture = std::make_shared<renderengine::impl::ExternalTexture>(
+            mGraphicBuffer, *mRenderEngine, renderengine::impl::ExternalTexture::Usage::WRITEABLE);
     auto [status, readyFence] = mRenderEngine
                                         ->drawLayers(mDisplaySettings, compositionLayers, texture,
                                                      true, std::move(bufferFence))
diff --git a/graphics/composer/2.2/vts/functional/OWNERS b/graphics/composer/2.2/vts/functional/OWNERS
index 31b0dc7..a4eb0ca 100644
--- a/graphics/composer/2.2/vts/functional/OWNERS
+++ b/graphics/composer/2.2/vts/functional/OWNERS
@@ -1,5 +1,6 @@
 # Bug component: 25423
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@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/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/OWNERS b/graphics/composer/2.3/vts/functional/OWNERS
index 31b0dc7..a4eb0ca 100644
--- a/graphics/composer/2.3/vts/functional/OWNERS
+++ b/graphics/composer/2.3/vts/functional/OWNERS
@@ -1,5 +1,6 @@
 # Bug component: 25423
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
 sumir@google.com
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/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/OWNERS b/graphics/composer/2.4/vts/functional/OWNERS
index 31b0dc7..a4eb0ca 100644
--- a/graphics/composer/2.4/vts/functional/OWNERS
+++ b/graphics/composer/2.4/vts/functional/OWNERS
@@ -1,5 +1,6 @@
 # Bug component: 25423
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
 sumir@google.com
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
index e9d9745..5593c57 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -51,6 +51,7 @@
   int getDisplayVsyncPeriod(long display);
   android.hardware.graphics.composer3.DisplayContentSample getDisplayedContentSample(long display, long maxFrames, long timestamp);
   android.hardware.graphics.composer3.DisplayContentSamplingAttributes getDisplayedContentSamplingAttributes(long display);
+  android.hardware.graphics.common.Transform getDisplayPhysicalOrientation(long display);
   android.hardware.graphics.composer3.HdrCapabilities getHdrCapabilities(long display);
   int getMaxVirtualDisplayCount();
   android.hardware.graphics.composer3.PerFrameMetadataKey[] getPerFrameMetadataKeys(long display);
@@ -61,6 +62,9 @@
   void registerCallback(in android.hardware.graphics.composer3.IComposerCallback callback);
   void setActiveConfig(long display, int config);
   android.hardware.graphics.composer3.VsyncPeriodChangeTimeline setActiveConfigWithConstraints(long display, int config, in android.hardware.graphics.composer3.VsyncPeriodChangeConstraints vsyncPeriodChangeConstraints);
+  void setBootDisplayConfig(long display, int config);
+  void clearBootDisplayConfig(long display);
+  int getPreferredBootDisplayConfig(long display);
   void setAutoLowLatencyMode(long display, boolean on);
   void setClientTargetSlotCount(long display, int clientTargetSlotCount);
   void setColorMode(long display, android.hardware.graphics.composer3.ColorMode mode, android.hardware.graphics.composer3.RenderIntent intent);
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index 3ab6329..c86b9bd 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.graphics.composer3;
 
+import android.hardware.graphics.common.Transform;
 import android.hardware.graphics.composer3.ClientTargetProperty;
 import android.hardware.graphics.composer3.ColorMode;
 import android.hardware.graphics.composer3.CommandResultPayload;
@@ -354,6 +355,23 @@
     DisplayContentSamplingAttributes getDisplayedContentSamplingAttributes(long display);
 
     /**
+     * Queries the physical orientation of a display. Orientation 'Transform::NONE'
+     * represents a display that doesn't require any transformation on layers
+     * to be presented at their natural orientation.
+     *
+     * @param display is the display where the physical orientation is queried.
+     *
+     * @return is one of the below values:
+     *         Transform::NONE
+     *         Transform::ROT_90
+     *         Transform::ROT_180
+     *         Transform::ROT_270
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display was passed in.
+     */
+    Transform getDisplayPhysicalOrientation(long display);
+
+    /**
      * Returns the high dynamic range (HDR) capabilities of the given display,
      * which are invariant with regard to the active configuration.
      *
@@ -549,6 +567,58 @@
             long display, int config, in VsyncPeriodChangeConstraints vsyncPeriodChangeConstraints);
 
     /**
+     * Sets the display config in which the device boots.
+     *
+     * If the device is unable to boot in this config for any reason (example HDMI display changed),
+     * the implementation should try to find a config which matches the resolution and refresh-rate
+     * of this config. If no such config exists, the implementation's preferred display config
+     * should be used.
+     *
+     * @param display is the display for which the boot config is set.
+     * @param config is the new boot config for the display.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_CONFIG when an invalid config id was passed in.
+     *
+     * @see getDisplayConfigs
+     * @see clearBootDisplayConfig
+     * @see getPreferredBootDisplayConfig
+     */
+    void setBootDisplayConfig(long display, int config);
+
+    /**
+     * Clears the boot display config.
+     *
+     * The device should boot in the implementation's preferred display config.
+     *
+     * @param display is the display for which the cached boot config is cleared.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     *
+     * @see getDisplayConfigs
+     * @see setBootDisplayConfig
+     * @see getPreferredBootDisplayConfig
+     */
+    void clearBootDisplayConfig(long display);
+
+    /**
+     * Returns the implementation's preferred display config.
+     *
+     * This is the display config used by the implementation at boot time, if the boot display
+     * config has not been requested yet, or if it has been previously cleared.
+     *
+     * @param display is the display to which the preferred config is queried.
+     * @return the implementation's preferred display config.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     *
+     * @see getDisplayConfigs
+     * @see setBootDisplayConfig
+     * @see clearBootDisplayConfig
+     */
+    int getPreferredBootDisplayConfig(long display);
+
+    /**
      * Requests the display to enable/disable its low latency mode.
      *
      * If the display is connected via HDMI 2.1, then Auto Low Latency Mode should be triggered. If
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
index 928e506..ff22817 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -716,6 +716,61 @@
     }
 }
 
+TEST_P(GraphicsComposerAidlTest, setBootDisplayConfig_BadDisplay) {
+    int32_t config = 0;
+    auto const error = mComposerClient->setBootDisplayConfig(mInvalidDisplayId, config);
+
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, setBootDisplayConfig_BadConfig) {
+    for (VtsDisplay& display : mDisplays) {
+        int32_t invalidConfigId = GetInvalidConfigId();
+        const auto error = mComposerClient->setBootDisplayConfig(display.get(), invalidConfigId);
+        EXPECT_FALSE(error.isOk());
+        EXPECT_EQ(IComposerClient::EX_BAD_CONFIG, error.getServiceSpecificError());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, setBootDisplayConfig) {
+    std::vector<int32_t> configs;
+    EXPECT_TRUE(mComposerClient->getDisplayConfigs(mPrimaryDisplay, &configs).isOk());
+    for (auto config : configs) {
+        EXPECT_TRUE(mComposerClient->setBootDisplayConfig(mPrimaryDisplay, config).isOk());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, clearBootDisplayConfig_BadDisplay) {
+    auto const error = mComposerClient->clearBootDisplayConfig(mInvalidDisplayId);
+
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, clearBootDisplayConfig) {
+    EXPECT_TRUE(mComposerClient->clearBootDisplayConfig(mPrimaryDisplay).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, getPreferredBootDisplayConfig_BadDisplay) {
+    int32_t config;
+    auto const error = mComposerClient->getPreferredBootDisplayConfig(mInvalidDisplayId, &config);
+
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, getPreferredBootDisplayConfig) {
+    int32_t preferredDisplayConfig = 0;
+    auto const error = mComposerClient->getPreferredBootDisplayConfig(mPrimaryDisplay,
+                                                                      &preferredDisplayConfig);
+    EXPECT_TRUE(error.isOk());
+
+    std::vector<int32_t> configs;
+    EXPECT_TRUE(mComposerClient->getDisplayConfigs(mPrimaryDisplay, &configs).isOk());
+    EXPECT_NE(configs.end(), std::find(configs.begin(), configs.end(), preferredDisplayConfig));
+}
+
 TEST_P(GraphicsComposerAidlTest, setAutoLowLatencyModeBadDisplay) {
     EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY,
               mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, true)
@@ -904,6 +959,33 @@
     EXPECT_TRUE(mComposerClient->getDisplayName(mPrimaryDisplay, &displayName).isOk());
 }
 
+TEST_P(GraphicsComposerAidlTest, GetDisplayPhysicalOrientationBadDisplay) {
+    Transform displayOrientation;
+    const auto error =
+            mComposerClient->getDisplayPhysicalOrientation(mInvalidDisplayId, &displayOrientation);
+
+    EXPECT_FALSE(error.isOk());
+    ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDisplayPhysicalOrientation) {
+    const auto allowedDisplayOrientations = std::array<Transform, 4>{
+            Transform::NONE,
+            Transform::ROT_90,
+            Transform::ROT_180,
+            Transform::ROT_270,
+    };
+
+    Transform displayOrientation;
+    const auto error =
+            mComposerClient->getDisplayPhysicalOrientation(mPrimaryDisplay, &displayOrientation);
+
+    EXPECT_TRUE(error.isOk());
+    EXPECT_NE(std::find(allowedDisplayOrientations.begin(), allowedDisplayOrientations.end(),
+                        displayOrientation),
+              allowedDisplayOrientations.end());
+}
+
 TEST_P(GraphicsComposerAidlTest, SetClientTargetSlotCount) {
     EXPECT_TRUE(
             mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount).isOk());
@@ -1698,6 +1780,26 @@
     ASSERT_TRUE(mReader.takeErrors().empty());
 }
 
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_BLOCKING_REGION) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    Rect empty{0, 0, 0, 0};
+    Rect unit{0, 0, 1, 1};
+
+    mWriter.setLayerBlockingRegion(mPrimaryDisplay, layer, std::vector<Rect>(1, empty));
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerBlockingRegion(mPrimaryDisplay, layer, std::vector<Rect>(1, unit));
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerBlockingRegion(mPrimaryDisplay, layer, std::vector<Rect>());
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
 TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_BLEND_MODE) {
     int64_t layer;
     EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
index deb5ac3..ee597a1 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
@@ -22,6 +22,7 @@
 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
 #include "include/RenderEngineVts.h"
 #include "renderengine/ExternalTexture.h"
+#include "renderengine/impl/ExternalTexture.h"
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop  // ignored "-Wconversion
@@ -300,12 +301,13 @@
 
 LayerSettings TestBufferLayer::toRenderEngineLayerSettings() {
     LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
-    layerSettings.source.buffer.buffer = std::make_shared<::android::renderengine::ExternalTexture>(
-            ::android::sp<::android::GraphicBuffer>::make(
-                    mGraphicBuffer->handle, ::android::GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
-                    static_cast<int32_t>(mPixelFormat), 1, mUsage, mStride),
-            mRenderEngine.getInternalRenderEngine(),
-            ::android::renderengine::ExternalTexture::Usage::READABLE);
+    layerSettings.source.buffer.buffer =
+            std::make_shared<::android::renderengine::impl::ExternalTexture>(
+                    ::android::sp<::android::GraphicBuffer>::make(
+                            mGraphicBuffer->handle, ::android::GraphicBuffer::CLONE_HANDLE, mWidth,
+                            mHeight, static_cast<int32_t>(mPixelFormat), 1, mUsage, mStride),
+                    mRenderEngine.getInternalRenderEngine(),
+                    ::android::renderengine::impl::ExternalTexture::Usage::READABLE);
 
     layerSettings.source.buffer.usePremultipliedAlpha = mBlendMode == BlendMode::PREMULTIPLIED;
 
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/RenderEngineVts.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/RenderEngineVts.cpp
index 50ce462..6ff064f 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/RenderEngineVts.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/RenderEngineVts.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "include/RenderEngineVts.h"
+#include "renderengine/impl/ExternalTexture.h"
 
 namespace aidl::android::hardware::graphics::composer3::vts {
 
@@ -62,9 +63,9 @@
                    std::back_insert_iterator(compositionLayers),
                    [](::android::renderengine::LayerSettings& settings)
                            -> ::android::renderengine::LayerSettings { return settings; });
-    auto texture = std::make_shared<::android::renderengine::ExternalTexture>(
+    auto texture = std::make_shared<::android::renderengine::impl::ExternalTexture>(
             mGraphicBuffer, *mRenderEngine,
-            ::android::renderengine::ExternalTexture::Usage::WRITEABLE);
+            ::android::renderengine::impl::ExternalTexture::Usage::WRITEABLE);
     auto [status, readyFence] = mRenderEngine
                                         ->drawLayers(mDisplaySettings, compositionLayers, texture,
                                                      true, std::move(bufferFence))
diff --git a/health/aidl/Android.bp b/health/aidl/Android.bp
index 22bb4fa..86bca69 100644
--- a/health/aidl/Android.bp
+++ b/health/aidl/Android.bp
@@ -62,9 +62,11 @@
         "android.hardware.health@2.0",
         "android.hardware.health@2.1",
     ],
-    defaults: [
-        "libbinder_ndk_host_user",
-    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
 
 java_library {
diff --git a/health/utils/libhealthshim/Android.bp b/health/utils/libhealthshim/Android.bp
index 311e951..42e4ea7 100644
--- a/health/utils/libhealthshim/Android.bp
+++ b/health/utils/libhealthshim/Android.bp
@@ -24,9 +24,11 @@
 cc_defaults {
     name: "libhealthshim_defaults",
     host_supported: true, // for testing
-    defaults: [
-        "libbinder_ndk_host_user",
-    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
     cflags: [
         "-Wall",
         "-Werror",
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..cd8d56b 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
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..c912c52 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,7 @@
   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);
   const int STATUS_OK = 0;
   const int STATUS_FAILED = 1;
   const int STATUS_CIPHER_SUITE_NOT_SUPPORTED = 2;
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IPresentationSession.aidl
similarity index 80%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IPresentationSession.aidl
index 295fde9..705dc29 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IPresentationSession.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -31,12 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.identity;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+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..9a0fa9e 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
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/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index 8ae293b..84d6ed0 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,6 +435,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.
+     *
      * @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.
      * @return a COSE_Sign1 signature described above.
@@ -442,6 +460,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.
+     *
      * @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.
      * @return a COSE_Sign1 signature described above.
@@ -456,6 +477,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..86be7f5 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -16,10 +16,11 @@
 
 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;
 
 /**
  * IIdentityCredentialStore provides an interface to a secure store for user identity documents.
@@ -105,7 +106,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.
@@ -241,4 +242,25 @@
      * @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);
 }
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/default/Android.bp b/identity/aidl/default/Android.bp
index 3de8d30..ca24afa 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,8 @@
         "libsoft_attestation_cert",
         "libpuresoftkeymasterdevice",
         "android.hardware.identity-support-lib",
-        "android.hardware.identity-V3-ndk",
-        "android.hardware.keymaster-V3-ndk",
+        "android.hardware.identity-V4-ndk",
+        "android.hardware.keymaster-V4-ndk",
     ],
 }
 
@@ -49,6 +50,7 @@
     vendor_available: true,
     srcs: [
         "libeic/EicCbor.c",
+        "libeic/EicSession.c",
         "libeic/EicPresentation.c",
         "libeic/EicProvisioning.c",
         "EicOpsImpl.cc",
@@ -100,8 +102,8 @@
         "libsoft_attestation_cert",
         "libpuresoftkeymasterdevice",
         "android.hardware.identity-support-lib",
-        "android.hardware.identity-V3-ndk",
-        "android.hardware.keymaster-V3-ndk",
+        "android.hardware.identity-V4-ndk",
+        "android.hardware.keymaster-V4-ndk",
         "android.hardware.identity-libeic-hal-common",
         "android.hardware.identity-libeic-library",
     ],
diff --git a/identity/aidl/default/EicOpsImpl.cc b/identity/aidl/default/EicOpsImpl.cc
index 8ec4cc9..c98a91e 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
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 f0307dc..91e634c 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,38 +53,110 @@
 
 // ----------------------------------------------------------------------
 
-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(),
-                                        docType.size(),
-                                        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 {};
+        return std::nullopt;
     }
     vector<uint8_t> pubKeyCert(publicKeyCertSize);
     memcpy(pubKeyCert.data(), publicKeyCert, publicKeyCertSize);
@@ -91,8 +164,11 @@
 }
 
 bool FakeSecureHardwareProvisioningProxy::startPersonalization(
-        int accessControlProfileCount, vector<int> entryCounts, const string& docType,
+        int accessControlProfileCount, const vector<int>& entryCounts, const string& docType,
         size_t expectedProofOfProvisioningSize) {
+    if (!validateId(__func__)) {
+        return false;
+    }
 
     if (!eicProvisioningStartPersonalization(&ctx_, accessControlProfileCount,
                                              entryCounts.data(),
@@ -108,13 +184,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(),
                 scratchSpace, sizeof(scratchSpace))) {
-        return {};
+        return std::nullopt;
     }
     return mac;
 }
@@ -122,6 +202,10 @@
 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];
     vector<uint8_t> uint8AccessControlProfileIds;
     for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
@@ -138,6 +222,10 @@
 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;
@@ -150,16 +238,20 @@
                 &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 {};
+        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;
 }
@@ -167,11 +259,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(), docType.size(),
                                                 encryptedCredentialKeys.data(), &size)) {
-        return {};
+        return std::nullopt;
     }
     encryptedCredentialKeys.resize(size);
     return encryptedCredentialKeys;
@@ -179,21 +275,200 @@
 
 // ----------------------------------------------------------------------
 
-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(), docType.size(),
-                               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);
@@ -201,7 +476,7 @@
     if (!eicPresentationGenerateSigningKeyPair(&ctx_, docType.c_str(), docType.size(), now,
                                                publicKeyCert, &publicKeyCertSize,
                                                signingKeyBlob.data())) {
-        return {};
+        return std::nullopt;
     }
 
     vector<uint8_t> cert;
@@ -213,33 +488,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(),
@@ -251,6 +537,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,
@@ -261,6 +551,10 @@
 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(),
@@ -268,12 +562,16 @@
                                                      userAuthenticationRequired, timeoutMillis,
                                                      secureUserId, mac.data(), &accessGranted,
                                                      scratchSpace, sizeof(scratchSpace))) {
-        return {};
+        return std::nullopt;
     }
     return accessGranted;
 }
 
 bool FakeSecureHardwarePresentationProxy::startRetrieveEntries() {
+    if (!validateId(__func__)) {
+        return false;
+    }
+
     return eicPresentationStartRetrieveEntries(&ctx_);
 }
 
@@ -281,6 +579,10 @@
         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;
@@ -294,6 +596,10 @@
 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++) {
@@ -324,6 +630,10 @@
 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++) {
@@ -337,16 +647,20 @@
                 nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(),
                 uint8AccessControlProfileIds.data(), uint8AccessControlProfileIds.size(),
                 scratchSpace, sizeof(scratchSpace))) {
-        return {};
+        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;
@@ -355,11 +669,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(), docType.size(), challenge.data(),
                                          challenge.size(), includeChallenge,
                                          proofOfDeletionCborSize, signatureOfToBeSigned.data())) {
-        return {};
+        return std::nullopt;
     }
     return signatureOfToBeSigned;
 }
@@ -367,11 +685,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(), 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..df98c7a 100644
--- a/identity/aidl/default/FakeSecureHardwareProxy.h
+++ b/identity/aidl/default/FakeSecureHardwareProxy.h
@@ -27,21 +27,23 @@
 //
 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,
+    bool startPersonalization(int accessControlProfileCount, const vector<int>& entryCounts,
                               const string& docType,
                               size_t expectedProofOfProvisioningSize) override;
 
@@ -67,21 +69,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 +195,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 +225,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..7678ecb 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,9 +1001,18 @@
 
 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_,
+            ndk::SharedRefBase::make<WritableIdentityCredential>(provisioningHwProxy, docType_,
                                                                  testCredential_);
     if (!wc->initializeForUpdate(encryptedCredentialKeys_)) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
diff --git a/identity/aidl/default/common/IdentityCredential.h b/identity/aidl/default/common/IdentityCredential.h
index ef9d133..2935fb8 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,11 +47,11 @@
 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)
         : hwProxyFactory_(hwProxyFactory),
-          hwProxy_(hwProxy),
           credentialData_(credentialData),
+          session_(std::move(session)),
           numStartRetrievalCalls_(0),
           expectedDeviceNameSpacesSize_(0) {}
 
@@ -94,10 +95,13 @@
                                               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_;
 
     // Set by initialize()
@@ -105,6 +109,9 @@
     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..4703ffe 100644
--- a/identity/aidl/default/common/IdentityCredentialStore.cpp
+++ b/identity/aidl/default/common/IdentityCredentialStore.cpp
@@ -20,6 +20,7 @@
 
 #include "IdentityCredential.h"
 #include "IdentityCredentialStore.h"
+#include "PresentationSession.h"
 #include "WritableIdentityCredential.h"
 
 namespace aidl::android::hardware::identity {
@@ -61,9 +62,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 */);
     auto ret = credential->initialize();
     if (ret != IIdentityCredentialStore::STATUS_OK) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -73,4 +73,25 @@
     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);
+    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();
+}
+
 }  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/IdentityCredentialStore.h b/identity/aidl/default/common/IdentityCredentialStore.h
index d35e632..77b894d 100644
--- a/identity/aidl/default/common/IdentityCredentialStore.h
+++ b/identity/aidl/default/common/IdentityCredentialStore.h
@@ -47,6 +47,9 @@
     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;
+
   private:
     sp<SecureHardwareProxyFactory> hwProxyFactory_;
 };
diff --git a/identity/aidl/default/common/PresentationSession.cpp b/identity/aidl/default/common/PresentationSession.cpp
new file mode 100644
index 0000000..fbd8972
--- /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);
+    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..76ca67b
--- /dev/null
+++ b/identity/aidl/default/common/PresentationSession.h
@@ -0,0 +1,83 @@
+/*
+ * 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)
+        : hwProxyFactory_(std::move(hwProxyFactory)), hwProxy_(std::move(hwProxy)) {}
+
+    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_;
+
+    // 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..a580444 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,7 @@
     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,
+    virtual bool startPersonalization(int accessControlProfileCount, const vector<int>& entryCounts,
                                       const string& docType,
                                       size_t expectedProofOfProvisioningSize) = 0;
 
@@ -98,8 +104,6 @@
 
     // Returns encryptedCredentialKeys (80 bytes).
     virtual optional<vector<uint8_t>> finishGetCredentialData(const string& docType) = 0;
-
-    virtual bool shutdown() = 0;
 };
 
 enum AccessCheckResult {
@@ -110,6 +114,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 +145,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 +206,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/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/EicCommon.h b/identity/aidl/default/libeic/EicCommon.h
index 476276e..2a08a35 100644
--- a/identity/aidl/default/libeic/EicCommon.h
+++ b/identity/aidl/default/libeic/EicCommon.h
@@ -21,6 +21,9 @@
 #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 = [
diff --git a/identity/aidl/default/libeic/EicOps.h b/identity/aidl/default/libeic/EicOps.h
index d4fcf0e..aa26e62 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).
@@ -295,6 +305,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 0d03ae9..104a559 100644
--- a/identity/aidl/default/libeic/EicPresentation.c
+++ b/identity/aidl/default/libeic/EicPresentation.c
@@ -16,11 +16,17 @@
 
 #include "EicPresentation.h"
 #include "EicCommon.h"
+#include "EicSession.h"
 
 #include <inttypes.h>
 
-bool eicPresentationInit(EicPresentation* ctx, bool testCredential, const char* docType,
-                         size_t docTypeLength, const uint8_t* encryptedCredentialKeys,
+// 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[EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101];
     bool expectPopSha256 = false;
@@ -39,6 +45,13 @@
     }
 
     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,
@@ -86,6 +99,23 @@
     if (expectPopSha256) {
         eicMemCpy(ctx->proofOfProvisioningSha256, credentialKeys + 54, EIC_SHA256_DIGEST_SIZE);
     }
+
+    eicDebug("Initialized presentation with id %" PRIu32, ctx->id);
+    return true;
+}
+
+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;
 }
 
@@ -174,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;
@@ -190,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;
@@ -330,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,
@@ -338,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;
@@ -354,6 +421,7 @@
                 challenge, secureUserId, authenticatorId, hardwareAuthenticatorType, timeStamp, mac,
                 macSize, verificationTokenChallenge, verificationTokenTimestamp,
                 verificationTokenSecurityLevel, verificationTokenMac, verificationTokenMacSize)) {
+        eicDebug("Error validating authToken");
         return false;
     }
     ctx->authTokenChallenge = challenge;
@@ -377,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;
         }
     }
@@ -490,6 +563,25 @@
                                const uint8_t signingKeyBlob[60], const char* docType,
                                size_t docTypeLength, unsigned int numNamespacesWithValues,
                                size_t expectedDeviceNamespacesSize) {
+    if (ctx->sessionId != 0) {
+        EicSession* session = eicSessionGetForId(ctx->sessionId);
+        if (session == NULL) {
+            eicDebug("Error looking up session for sessionId %" PRIu32, ctx->sessionId);
+            return false;
+        }
+        EicSha256Ctx sha256;
+        uint8_t sessionTranscriptSha256[EIC_SHA256_DIGEST_SIZE];
+        eicOpsSha256Init(&sha256);
+        eicOpsSha256Update(&sha256, sessionTranscript, sessionTranscriptSize);
+        eicOpsSha256Final(&sha256, sessionTranscriptSha256);
+        if (eicCryptoMemCmp(sessionTranscriptSha256, session->sessionTranscriptSha256,
+                            EIC_SHA256_DIGEST_SIZE) != 0) {
+            eicDebug("SessionTranscript mismatch");
+            return false;
+        }
+        readerEphemeralPublicKey = session->readerEphemeralPublicKey;
+    }
+
     uint8_t signingKeyPriv[EIC_P256_PRIV_KEY_SIZE];
     if (!eicOpsDecryptAes128Gcm(ctx->storageKey, signingKeyBlob, 60, (const uint8_t*)docType,
                                 docTypeLength, signingKeyPriv)) {
diff --git a/identity/aidl/default/libeic/EicPresentation.h b/identity/aidl/default/libeic/EicPresentation.h
index 6f7f432..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,10 +103,18 @@
     EicCbor cbor;
 } EicPresentation;
 
-bool eicPresentationInit(EicPresentation* ctx, bool testCredential, const char* docType,
-                         size_t docTypeLength, const uint8_t* encryptedCredentialKeys,
+// 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 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,
diff --git a/identity/aidl/default/libeic/EicProvisioning.c b/identity/aidl/default/libeic/EicProvisioning.c
index c9df4fd..a241b71 100644
--- a/identity/aidl/default/libeic/EicProvisioning.c
+++ b/identity/aidl/default/libeic/EicProvisioning.c
@@ -17,8 +17,21 @@
 #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;
@@ -47,6 +60,13 @@
     }
 
     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,
@@ -96,6 +116,21 @@
     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,
diff --git a/identity/aidl/default/libeic/EicProvisioning.h b/identity/aidl/default/libeic/EicProvisioning.h
index 92f1e4a..d94f8f1 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];
 
@@ -68,6 +71,10 @@
                                   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,
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 20c8896..d89fc9a 100644
--- a/identity/aidl/default/libeic/libeic.h
+++ b/identity/aidl/default/libeic/libeic.h
@@ -27,10 +27,11 @@
  */
 #define EIC_INSIDE_LIBEIC_H
 #include "EicCbor.h"
+#include "EicCommon.h"
 #include "EicOps.h"
 #include "EicPresentation.h"
 #include "EicProvisioning.h"
-#include "EicCommon.h"
+#include "EicSession.h"
 #undef EIC_INSIDE_LIBEIC_H
 
 #ifdef __cplusplus
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index e5de91e..7b6f2c8 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -28,6 +28,7 @@
         "EndToEndTests.cpp",
         "TestCredentialTests.cpp",
         "AuthenticationKeyTests.cpp",
+        "PresentationSessionTests.cpp",
     ],
     shared_libs: [
         "libbinder",
@@ -40,9 +41,9 @@
         "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",
+        "android.hardware.identity-V4-cpp",
+        "android.hardware.keymaster-V4-cpp",
+        "android.hardware.keymaster-V4-ndk",
         "libkeymaster4support",
         "libkeymaster4_1support",
     ],
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/input/common/aidl/Android.bp b/input/common/aidl/Android.bp
new file mode 100644
index 0000000..6cf64a6
--- /dev/null
+++ b/input/common/aidl/Android.bp
@@ -0,0 +1,22 @@
+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.input.common",
+    srcs: ["android/hardware/input/common/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            enabled: false,
+        },
+    },
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Action.aidl
similarity index 81%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Action.aidl
index af7bc3c..a2e0381 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Action.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,16 +31,20 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@Backing(type="byte") @VintfStability
-enum Error {
-  UNKNOWN = 0,
-  HW_UNAVAILABLE = 1,
-  UNABLE_TO_PROCESS = 2,
-  TIMEOUT = 3,
-  NO_SPACE = 4,
-  CANCELED = 5,
-  UNABLE_TO_REMOVE = 6,
-  VENDOR = 7,
-  BAD_CALIBRATION = 8,
+package android.hardware.input.common;
+@Backing(type="int") @VintfStability
+enum Action {
+  DOWN = 0,
+  UP = 1,
+  MOVE = 2,
+  CANCEL = 3,
+  OUTSIDE = 4,
+  POINTER_DOWN = 5,
+  POINTER_UP = 6,
+  HOVER_MOVE = 7,
+  SCROLL = 8,
+  HOVER_ENTER = 9,
+  HOVER_EXIT = 10,
+  BUTTON_PRESS = 11,
+  BUTTON_RELEASE = 12,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Axis.aidl
similarity index 65%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Axis.aidl
index c51aa03..2114c7d 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Axis.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,20 +31,52 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@Backing(type="byte") @VintfStability
-enum AcquiredInfo {
-  UNKNOWN = 0,
-  GOOD = 1,
-  PARTIAL = 2,
-  INSUFFICIENT = 3,
-  SENSOR_DIRTY = 4,
-  TOO_SLOW = 5,
-  TOO_FAST = 6,
-  VENDOR = 7,
-  START = 8,
-  TOO_DARK = 9,
-  TOO_BRIGHT = 10,
-  IMMOBILE = 11,
-  RETRYING_CAPTURE = 12,
+package android.hardware.input.common;
+@Backing(type="int") @VintfStability
+enum Axis {
+  X = 0,
+  Y = 1,
+  PRESSURE = 2,
+  SIZE = 3,
+  TOUCH_MAJOR = 4,
+  TOUCH_MINOR = 5,
+  TOOL_MAJOR = 6,
+  TOOL_MINOR = 7,
+  ORIENTATION = 8,
+  VSCROLL = 9,
+  HSCROLL = 10,
+  Z = 11,
+  RX = 12,
+  RY = 13,
+  RZ = 14,
+  HAT_X = 15,
+  HAT_Y = 16,
+  LTRIGGER = 17,
+  RTRIGGER = 18,
+  THROTTLE = 19,
+  RUDDER = 20,
+  WHEEL = 21,
+  GAS = 22,
+  BRAKE = 23,
+  DISTANCE = 24,
+  TILT = 25,
+  SCROLL = 26,
+  RELATIVE_X = 27,
+  RELATIVE_Y = 28,
+  GENERIC_1 = 32,
+  GENERIC_2 = 33,
+  GENERIC_3 = 34,
+  GENERIC_4 = 35,
+  GENERIC_5 = 36,
+  GENERIC_6 = 37,
+  GENERIC_7 = 38,
+  GENERIC_8 = 39,
+  GENERIC_9 = 40,
+  GENERIC_10 = 41,
+  GENERIC_11 = 42,
+  GENERIC_12 = 43,
+  GENERIC_13 = 44,
+  GENERIC_14 = 45,
+  GENERIC_15 = 46,
+  GENERIC_16 = 47,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Button.aidl
similarity index 84%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Button.aidl
index 295fde9..10ad65a 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Button.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,15 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+package android.hardware.input.common;
+@Backing(type="int") @VintfStability
+enum Button {
+  NONE = 0,
+  PRIMARY = 1,
+  SECONDARY = 2,
+  TERTIARY = 4,
+  BACK = 8,
+  FORWARD = 16,
+  STYLUS_PRIMARY = 32,
+  STYLUS_SECONDARY = 64,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Classification.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Classification.aidl
index 295fde9..ddd5246 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Classification.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+package android.hardware.input.common;
+@Backing(type="byte") @VintfStability
+enum Classification {
+  NONE = 0,
+  AMBIGUOUS_GESTURE = 1,
+  DEEP_PRESS = 2,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/EdgeFlag.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/EdgeFlag.aidl
index 295fde9..1040049 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/EdgeFlag.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+package android.hardware.input.common;
+@Backing(type="int") @VintfStability
+enum EdgeFlag {
+  NONE = 0,
+  TOP = 1,
+  BOTTOM = 2,
+  LEFT = 4,
+  RIGHT = 8,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Flag.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Flag.aidl
index 295fde9..d3fcd9f 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Flag.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+package android.hardware.input.common;
+@Backing(type="int") @VintfStability
+enum Flag {
+  WINDOW_IS_OBSCURED = 1,
+  IS_GENERATED_GESTURE = 8,
+  TAINTED = -2147483648,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Meta.aidl
similarity index 75%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Meta.aidl
index c51aa03..2c229f9 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Meta.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,20 +31,25 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@Backing(type="byte") @VintfStability
-enum AcquiredInfo {
-  UNKNOWN = 0,
-  GOOD = 1,
-  PARTIAL = 2,
-  INSUFFICIENT = 3,
-  SENSOR_DIRTY = 4,
-  TOO_SLOW = 5,
-  TOO_FAST = 6,
-  VENDOR = 7,
-  START = 8,
-  TOO_DARK = 9,
-  TOO_BRIGHT = 10,
-  IMMOBILE = 11,
-  RETRYING_CAPTURE = 12,
+package android.hardware.input.common;
+@Backing(type="int") @VintfStability
+enum Meta {
+  NONE = 0,
+  ALT_ON = 2,
+  ALT_LEFT_ON = 16,
+  ALT_RIGHT_ON = 32,
+  SHIFT_ON = 1,
+  SHIFT_LEFT_ON = 64,
+  SHIFT_RIGHT_ON = 128,
+  SYM_ON = 4,
+  FUNCTION_ON = 8,
+  CTRL_ON = 4096,
+  CTRL_LEFT_ON = 8192,
+  CTRL_RIGHT_ON = 16384,
+  META_ON = 65536,
+  META_LEFT_ON = 131072,
+  META_RIGHT_ON = 262144,
+  CAPS_LOCK_ON = 1048576,
+  NUM_LOCK_ON = 2097152,
+  SCROLL_LOCK_ON = 4194304,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/MotionEvent.aidl
similarity index 66%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/MotionEvent.aidl
index 295fde9..84af4bf 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/MotionEvent.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,26 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.input.common;
 @VintfStability
-parcelable SensorLocation {
+parcelable MotionEvent {
+  int deviceId;
+  android.hardware.input.common.Source source;
   int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+  long downTime;
+  long eventTime;
+  android.hardware.input.common.Action action;
+  byte actionIndex;
+  android.hardware.input.common.Button actionButton;
+  android.hardware.input.common.Flag flags;
+  android.hardware.input.common.PolicyFlag policyFlags;
+  android.hardware.input.common.EdgeFlag edgeFlags;
+  android.hardware.input.common.Meta metaState;
+  android.hardware.input.common.Button buttonState;
+  float xPrecision;
+  float yPrecision;
+  android.hardware.input.common.PointerProperties[] pointerProperties;
+  android.hardware.input.common.PointerCoords[] pointerCoords;
+  int deviceTimestamp;
+  android.hardware.input.common.VideoFrame[] frames;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/PointerCoords.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/PointerCoords.aidl
index 295fde9..353a106 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/PointerCoords.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.input.common;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable PointerCoords {
+  long bits;
+  float[] values;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/PointerProperties.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/PointerProperties.aidl
index 295fde9..a49581b 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/PointerProperties.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.input.common;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable PointerProperties {
+  int id;
+  android.hardware.input.common.ToolType toolType;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/PolicyFlag.aidl
similarity index 81%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/PolicyFlag.aidl
index af7bc3c..247e868 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/PolicyFlag.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,16 +31,17 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@Backing(type="byte") @VintfStability
-enum Error {
-  UNKNOWN = 0,
-  HW_UNAVAILABLE = 1,
-  UNABLE_TO_PROCESS = 2,
-  TIMEOUT = 3,
-  NO_SPACE = 4,
-  CANCELED = 5,
-  UNABLE_TO_REMOVE = 6,
-  VENDOR = 7,
-  BAD_CALIBRATION = 8,
+package android.hardware.input.common;
+@Backing(type="int") @VintfStability
+enum PolicyFlag {
+  WAKE = 1,
+  VIRTUAL = 2,
+  FUNCTION = 4,
+  GESTURE = 8,
+  INJECTED = 16777216,
+  TRUSTED = 33554432,
+  FILTERED = 67108864,
+  DISABLE_KEY_REPEAT = 134217728,
+  INTERACTIVE = 536870912,
+  PASS_TO_USER = 1073741824,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Source.aidl
similarity index 77%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Source.aidl
index c51aa03..24d02cd 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/Source.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,20 +31,23 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@Backing(type="byte") @VintfStability
-enum AcquiredInfo {
+package android.hardware.input.common;
+@Backing(type="int") @VintfStability
+enum Source {
   UNKNOWN = 0,
-  GOOD = 1,
-  PARTIAL = 2,
-  INSUFFICIENT = 3,
-  SENSOR_DIRTY = 4,
-  TOO_SLOW = 5,
-  TOO_FAST = 6,
-  VENDOR = 7,
-  START = 8,
-  TOO_DARK = 9,
-  TOO_BRIGHT = 10,
-  IMMOBILE = 11,
-  RETRYING_CAPTURE = 12,
+  KEYBOARD = 257,
+  DPAD = 513,
+  GAMEPAD = 1025,
+  TOUCHSCREEN = 4098,
+  MOUSE = 8194,
+  STYLUS = 16386,
+  BLUETOOTH_STYLUS = 49154,
+  TRACKBALL = 65540,
+  MOUSE_RELATIVE = 131076,
+  TOUCHPAD = 1048584,
+  TOUCH_NAVIGATION = 2097152,
+  ROTARY_ENCODER = 4194304,
+  JOYSTICK = 16777232,
+  SENSOR = 67108864,
+  ANY = -256,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/SourceClass.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/SourceClass.aidl
index 295fde9..96eede2 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/SourceClass.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,13 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-@VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+package android.hardware.input.common;
+@Backing(type="byte") @VintfStability
+enum SourceClass {
+  NONE = 0,
+  BUTTON = 1,
+  POINTER = 2,
+  NAVIGATION = 4,
+  POSITION = 8,
+  JOYSTICK = 16,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/ToolType.aidl
similarity index 86%
rename from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
rename to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/ToolType.aidl
index 9c208c4..ac1b69d 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/ToolType.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,13 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.input.common;
 @Backing(type="byte") @VintfStability
-enum FingerprintSensorType {
+enum ToolType {
   UNKNOWN = 0,
-  REAR = 1,
-  UNDER_DISPLAY_ULTRASONIC = 2,
-  UNDER_DISPLAY_OPTICAL = 3,
-  POWER_BUTTON = 4,
-  HOME_BUTTON = 5,
+  FINGER = 1,
+  STYLUS = 2,
+  MOUSE = 3,
+  ERASER = 4,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/VideoFrame.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/VideoFrame.aidl
index 295fde9..14985c5 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/input/common/aidl/aidl_api/android.hardware.input.common/current/android/hardware/input/common/VideoFrame.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,12 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.input.common;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable VideoFrame {
+  char[] data;
+  int height;
+  int width;
+  long timestamp;
 }
diff --git a/input/common/aidl/android/hardware/input/common/Action.aidl b/input/common/aidl/android/hardware/input/common/Action.aidl
new file mode 100644
index 0000000..ebe5e67
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/Action.aidl
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+/**
+ * Motion event actions
+ */
+@VintfStability
+@Backing(type="int")
+enum Action {
+    /**
+     * A pressed gesture has started, the motion contains the initial starting location.
+     */
+    DOWN = 0,
+    /**
+     * A pressed gesture has finished, the motion contains the final release location
+     * as well as any intermediate points since the last down or move event.
+     */
+    UP = 1,
+    /**
+     * A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and
+     * AMOTION_EVENT_ACTION_UP). The motion contains the most recent point.
+     */
+    MOVE = 2,
+    /**
+     * The current gesture has been aborted.
+     * You will not receive any more points in it. You must treat this as
+     * an up event, but not perform any action that you normally would.
+     */
+    CANCEL = 3,
+    /**
+     * A movement has happened outside of the normal bounds of the UI element.
+     * This does not provide a full gesture, but only the initial location of the movement/touch.
+     */
+    OUTSIDE = 4,
+    /**
+     * A non-primary pointer has gone down.
+     */
+    POINTER_DOWN = 5,
+    /**
+     * A non-primary pointer has gone up.
+     */
+    POINTER_UP = 6,
+    /**
+     * A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE).
+     * The motion contains the most recent point, as well as any intermediate points since
+     * the last hover move event.
+     */
+    HOVER_MOVE = 7,
+    /**
+     * The motion event contains relative vertical and/or horizontal scroll offsets.
+     * Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL
+     * and AMOTION_EVENT_AXIS_HSCROLL.
+     * The pointer may or may not be down when this event is dispatched.
+     * The framework will always deliver this action to the window under the pointer, which
+     * may not be the window currently touched.
+     */
+    SCROLL = 8,
+    /**
+     * The pointer is not down but has entered the boundaries of a window or view.
+     */
+    HOVER_ENTER = 9,
+    /**
+     * The pointer is not down but has exited the boundaries of a window or view.
+     */
+    HOVER_EXIT = 10,
+    /**
+     * One or more buttons have been pressed.
+     */
+    BUTTON_PRESS = 11,
+    /**
+     * One or more buttons have been released.
+     */
+    BUTTON_RELEASE = 12,
+}
diff --git a/input/common/aidl/android/hardware/input/common/Axis.aidl b/input/common/aidl/android/hardware/input/common/Axis.aidl
new file mode 100644
index 0000000..1150949
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/Axis.aidl
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+/**
+ * Constants that identify each individual axis of a motion event.
+ * Each value represents a bit position. The user is expected to manually shift
+ * to the desired position (e.g., 1 << Axis.X) when reading or writing these
+ * from a bitfield manually.
+ */
+@VintfStability
+@Backing(type="int")
+enum Axis {
+    /**
+     * Axis constant: X axis of a motion event.
+     *
+     * - For a touch screen, reports the absolute X screen position of the center of
+     * the touch contact area.  The units are display pixels.
+     * - For a touch pad, reports the absolute X surface position of the center of the touch
+     * contact area. The units are device-dependent.
+     * - For a mouse, reports the absolute X screen position of the mouse pointer.
+     * The units are display pixels.
+     * - For a trackball, reports the relative horizontal displacement of the trackball.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     * - For a joystick, reports the absolute X position of the joystick.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     */
+    X = 0,
+    /**
+     * Axis constant: Y axis of a motion event.
+     *
+     * - For a touch screen, reports the absolute Y screen position of the center of
+     * the touch contact area.  The units are display pixels.
+     * - For a touch pad, reports the absolute Y surface position of the center of the touch
+     * contact area. The units are device-dependent.
+     * - For a mouse, reports the absolute Y screen position of the mouse pointer.
+     * The units are display pixels.
+     * - For a trackball, reports the relative vertical displacement of the trackball.
+     * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+     * - For a joystick, reports the absolute Y position of the joystick.
+     * The value is normalized to a range from -1.0 (up or far) to 1.0 (down or near).
+     */
+    Y = 1,
+    /**
+     * Axis constant: Pressure axis of a motion event.
+     *
+     * - For a touch screen or touch pad, reports the approximate pressure applied to the surface
+     * by a finger or other tool.  The value is normalized to a range from
+     * 0 (no pressure at all) to 1 (normal pressure), although values higher than 1
+     * may be generated depending on the calibration of the input device.
+     * - For a trackball, the value is set to 1 if the trackball button is pressed
+     * or 0 otherwise.
+     * - For a mouse, the value is set to 1 if the primary mouse button is pressed
+     * or 0 otherwise.
+     */
+    PRESSURE = 2,
+    /**
+     * Axis constant: Size axis of a motion event.
+     *
+     * - For a touch screen or touch pad, reports the approximate size of the contact area in
+     * relation to the maximum detectable size for the device.  The value is normalized
+     * to a range from 0 (smallest detectable size) to 1 (largest detectable size),
+     * although it is not a linear scale. This value is of limited use.
+     * To obtain calibrated size information, see
+     * {@link TOUCH_MAJOR} or {@link TOOL_MAJOR}.
+     */
+    SIZE = 3,
+    /**
+     * Axis constant: TouchMajor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the major axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are display pixels.
+     * - For a touch pad, reports the length of the major axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are device-dependent.
+     */
+    TOUCH_MAJOR = 4,
+    /**
+     * Axis constant: TouchMinor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the minor axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are display pixels.
+     * - For a touch pad, reports the length of the minor axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are device-dependent.
+     *
+     * When the touch is circular, the major and minor axis lengths will be equal to one another.
+     */
+    TOUCH_MINOR = 5,
+    /**
+     * Axis constant: ToolMajor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the major axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * - For a touch pad, reports the length of the major axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * The units are device-dependent.
+     *
+     * When the touch is circular, the major and minor axis lengths will be equal to one another.
+     *
+     * The tool size may be larger than the touch size since the tool may not be fully
+     * in contact with the touch sensor.
+     */
+    TOOL_MAJOR = 6,
+    /**
+     * Axis constant: ToolMinor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the minor axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * - For a touch pad, reports the length of the minor axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * The units are device-dependent.
+     *
+     * When the touch is circular, the major and minor axis lengths will be equal to one another.
+     *
+     * The tool size may be larger than the touch size since the tool may not be fully
+     * in contact with the touch sensor.
+     */
+    TOOL_MINOR = 7,
+    /**
+     * Axis constant: Orientation axis of a motion event.
+     *
+     * - For a touch screen or touch pad, reports the orientation of the finger
+     * or tool in radians relative to the vertical plane of the device.
+     * An angle of 0 radians indicates that the major axis of contact is oriented
+     * upwards, is perfectly circular or is of unknown orientation.  A positive angle
+     * indicates that the major axis of contact is oriented to the right.  A negative angle
+     * indicates that the major axis of contact is oriented to the left.
+     * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
+     * (finger pointing fully right).
+     * - For a stylus, the orientation indicates the direction in which the stylus
+     * is pointing in relation to the vertical axis of the current orientation of the screen.
+     * The range is from -PI radians to PI radians, where 0 is pointing up,
+     * -PI/2 radians is pointing left, -PI or PI radians is pointing down, and PI/2 radians
+     * is pointing right.  See also {@link TILT}.
+     */
+    ORIENTATION = 8,
+    /**
+     * Axis constant: Vertical Scroll axis of a motion event.
+     *
+     * - For a mouse, reports the relative movement of the vertical scroll wheel.
+     * The value is normalized to a range from -1.0 (down) to 1.0 (up).
+     *
+     * The framework may use this axis to scroll views vertically.
+     */
+    VSCROLL = 9,
+    /**
+     * Axis constant: Horizontal Scroll axis of a motion event.
+     *
+     * - For a mouse, reports the relative movement of the horizontal scroll wheel.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     *
+     * The framework may use this axis to scroll views horizontally.
+     */
+    HSCROLL = 10,
+    /**
+     * Axis constant: Z axis of a motion event.
+     *
+     * - For a joystick, reports the absolute Z position of the joystick.
+     * The value is normalized to a range from -1.0 (high) to 1.0 (low).
+     * <em>On game pads with two analog joysticks, this axis is often reinterpreted
+     * to report the absolute X position of the second joystick instead.</em>
+     */
+    Z = 11,
+    /**
+     * Axis constant: X Rotation axis of a motion event.
+     *
+     * - For a joystick, reports the absolute rotation angle about the X axis.
+     * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+     */
+    RX = 12,
+    /**
+     * Axis constant: Y Rotation axis of a motion event.
+     *
+     * - For a joystick, reports the absolute rotation angle about the Y axis.
+     * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+     */
+    RY = 13,
+    /**
+     * Axis constant: Z Rotation axis of a motion event.
+     *
+     * - For a joystick, reports the absolute rotation angle about the Z axis.
+     * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+     * On game pads with two analog joysticks, this axis is often reinterpreted
+     * to report the absolute Y position of the second joystick instead.
+     */
+    RZ = 14,
+    /**
+     * Axis constant: Hat X axis of a motion event.
+     *
+     * - For a joystick, reports the absolute X position of the directional hat control.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     */
+    HAT_X = 15,
+    /**
+     * Axis constant: Hat Y axis of a motion event.
+     *
+     * - For a joystick, reports the absolute Y position of the directional hat control.
+     * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+     */
+    HAT_Y = 16,
+    /**
+     * Axis constant: Left Trigger axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the left trigger control.
+     * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+     */
+    LTRIGGER = 17,
+    /**
+     * Axis constant: Right Trigger axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the right trigger control.
+     * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+     */
+    RTRIGGER = 18,
+    /**
+     * Axis constant: Throttle axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the throttle control.
+     * The value is normalized to a range from 0.0 (fully open) to 1.0 (fully closed).
+     */
+    THROTTLE = 19,
+    /**
+     * Axis constant: Rudder axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the rudder control.
+     * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+     */
+    RUDDER = 20,
+    /**
+     * Axis constant: Wheel axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the steering wheel control.
+     * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+     */
+    WHEEL = 21,
+    /**
+     * Axis constant: Gas axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the gas (accelerator) control.
+     * The value is normalized to a range from 0.0 (no acceleration)
+     * to 1.0 (maximum acceleration).
+     */
+    GAS = 22,
+    /**
+     * Axis constant: Brake axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the brake control.
+     * The value is normalized to a range from 0.0 (no braking) to 1.0 (maximum braking).
+     */
+    BRAKE = 23,
+    /**
+     * Axis constant: Distance axis of a motion event.
+     *
+     * - For a stylus, reports the distance of the stylus from the screen.
+     * A value of 0.0 indicates direct contact and larger values indicate increasing
+     * distance from the surface.
+     */
+    DISTANCE = 24,
+    /**
+     * Axis constant: Tilt axis of a motion event.
+     *
+     * - For a stylus, reports the tilt angle of the stylus in radians where
+     * 0 radians indicates that the stylus is being held perpendicular to the
+     * surface, and PI/2 radians indicates that the stylus is being held flat
+     * against the surface.
+     */
+    TILT = 25,
+    /**
+     * Axis constant:  Generic scroll axis of a motion event.
+     *
+     * - This is used for scroll axis motion events that can't be classified as strictly
+     *   vertical or horizontal. The movement of a rotating scroller is an example of this.
+     */
+    SCROLL = 26,
+    /**
+     * Axis constant: The movement of x position of a motion event.
+     *
+     * - For a mouse, reports a difference of x position between the previous position.
+     * This is useful when pointer is captured, in that case the mouse pointer doesn't
+     * change the location but this axis reports the difference which allows the app
+     * to see how the mouse is moved.
+     */
+    RELATIVE_X = 27,
+    /**
+     * Axis constant: The movement of y position of a motion event.
+     *
+     * Same as {@link RELATIVE_X}, but for y position.
+     */
+    RELATIVE_Y = 28,
+    /**
+     * Axis constant: Generic 1 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_1 = 32,
+    /**
+     * Axis constant: Generic 2 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_2 = 33,
+    /**
+     * Axis constant: Generic 3 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_3 = 34,
+    /**
+     * Axis constant: Generic 4 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_4 = 35,
+    /**
+     * Axis constant: Generic 5 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_5 = 36,
+    /**
+     * Axis constant: Generic 6 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_6 = 37,
+    /**
+     * Axis constant: Generic 7 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_7 = 38,
+    /**
+     * Axis constant: Generic 8 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_8 = 39,
+    /**
+     * Axis constant: Generic 9 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_9 = 40,
+    /**
+     * Axis constant: Generic 10 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_10 = 41,
+    /**
+     * Axis constant: Generic 11 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_11 = 42,
+    /**
+     * Axis constant: Generic 12 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_12 = 43,
+    /**
+     * Axis constant: Generic 13 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_13 = 44,
+    /**
+     * Axis constant: Generic 14 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_14 = 45,
+    /**
+     * Axis constant: Generic 15 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_15 = 46,
+    /**
+     * Axis constant: Generic 16 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_16 = 47,
+}
diff --git a/input/common/aidl/android/hardware/input/common/Button.aidl b/input/common/aidl/android/hardware/input/common/Button.aidl
new file mode 100644
index 0000000..4bbd5f5
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/Button.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+/**
+ * Buttons that are associated with motion events.
+ */
+@VintfStability
+@Backing(type="int")
+enum Button {
+    NONE = 0,
+    PRIMARY = 1 << 0,
+    SECONDARY = 1 << 1,
+    TERTIARY = 1 << 2,
+    BACK = 1 << 3,
+    FORWARD = 1 << 4,
+    STYLUS_PRIMARY = 1 << 5,
+    STYLUS_SECONDARY = 1 << 6,
+}
diff --git a/input/common/aidl/android/hardware/input/common/Classification.aidl b/input/common/aidl/android/hardware/input/common/Classification.aidl
new file mode 100644
index 0000000..f573174
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/Classification.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+/**
+ * Classification of the current gesture, if available.
+ */
+@VintfStability
+@Backing(type="byte")
+enum Classification {
+    NONE = 0,
+    /**
+     * Too early to classify the gesture, need more events.
+     */
+    AMBIGUOUS_GESTURE = 1,
+    /**
+     * User is force-pressing the screen.
+     */
+    DEEP_PRESS = 2,
+}
diff --git a/input/common/aidl/android/hardware/input/common/EdgeFlag.aidl b/input/common/aidl/android/hardware/input/common/EdgeFlag.aidl
new file mode 100644
index 0000000..8d22635
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/EdgeFlag.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+/**
+ * Edge flags
+ */
+@VintfStability
+@Backing(type="int")
+enum EdgeFlag {
+    /**
+     * No edges are intersected
+     */
+    NONE = 0,
+    /**
+     * Motion intersected top edge of the screen
+     */
+    TOP = 1 << 0,
+    /**
+     * Motion intersected bottom edge of the screen
+     */
+    BOTTOM = 1 << 1,
+    /**
+     * Motion intersected left edge of the screen
+     */
+    LEFT = 1 << 2,
+    /**
+     * Motion intersected right edge of the screen
+     */
+    RIGHT = 1 << 3,
+}
diff --git a/input/common/aidl/android/hardware/input/common/Flag.aidl b/input/common/aidl/android/hardware/input/common/Flag.aidl
new file mode 100644
index 0000000..600bdd3
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/Flag.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+/**
+ * Motion event flags
+ */
+@VintfStability
+@Backing(type="int")
+enum Flag {
+    /**
+     * Indicates that the window that received this motion event is partly
+     * or wholly obscured by another visible window above it. This flag is set to true
+     * even if the event did not directly pass through the obscured area.
+     * A security sensitive application can check this flag to identify situations in which
+     * a malicious application may have covered up part of its content for the purpose
+     * of misleading the user or hijacking touches. An appropriate response might be
+     * to drop the suspect touches or to take additional precautions to confirm the user's
+     * actual intent.
+     */
+    WINDOW_IS_OBSCURED = 1 << 0,
+    /**
+     * This flag indicates that the event has been generated by a gesture generator. It
+     * could be used, for example, to determine whether touch slop should be applied.
+     */
+    IS_GENERATED_GESTURE = 1 << 3,
+    /**
+     * Motion event is inconsistent with previously sent motion events.
+     */
+    TAINTED = 1 << 31,
+}
diff --git a/input/common/aidl/android/hardware/input/common/Meta.aidl b/input/common/aidl/android/hardware/input/common/Meta.aidl
new file mode 100644
index 0000000..9ccf11b
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/Meta.aidl
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+/**
+ * Meta key / modifier state
+ */
+@VintfStability
+@Backing(type="int")
+enum Meta {
+    NONE = 0,
+    /**
+     * One of the ALT meta keys is pressed.
+     */
+    ALT_ON = 1 << 1,
+    /**
+     * The left ALT meta key is pressed.
+     */
+    ALT_LEFT_ON = 1 << 4,
+    /**
+     * The right ALT meta key is pressed.
+     */
+    ALT_RIGHT_ON = 1 << 5,
+    /**
+     * One of the SHIFT meta keys is pressed.
+     */
+    SHIFT_ON = 1 << 0,
+    /**
+     * The left SHIFT meta key is pressed.
+     */
+    SHIFT_LEFT_ON = 1 << 6,
+    /**
+     * The right SHIFT meta key is pressed.
+     */
+    SHIFT_RIGHT_ON = 1 << 7,
+    /**
+     * The SYM meta key is pressed.
+     */
+    SYM_ON = 1 << 2,
+    /**
+     * The FUNCTION meta key is pressed.
+     */
+    FUNCTION_ON = 1 << 3,
+    /**
+     * One of the CTRL meta keys is pressed.
+     */
+    CTRL_ON = 1 << 12,
+    /**
+     * The left CTRL meta key is pressed.
+     */
+    CTRL_LEFT_ON = 1 << 13,
+    /**
+     * The right CTRL meta key is pressed.
+     */
+    CTRL_RIGHT_ON = 1 << 14,
+    /**
+     * One of the META meta keys is pressed.
+     */
+    META_ON = 1 << 16,
+    /**
+     * The left META meta key is pressed.
+     */
+    META_LEFT_ON = 1 << 17,
+    /**
+     * The right META meta key is pressed.
+     */
+    META_RIGHT_ON = 1 << 18,
+    /**
+     * The CAPS LOCK meta key is on.
+     */
+    CAPS_LOCK_ON = 1 << 20,
+    /**
+     * The NUM LOCK meta key is on.
+     */
+    NUM_LOCK_ON = 1 << 21,
+    /**
+     * The SCROLL LOCK meta key is on.
+     */
+    SCROLL_LOCK_ON = 1 << 22,
+}
diff --git a/input/common/aidl/android/hardware/input/common/MotionEvent.aidl b/input/common/aidl/android/hardware/input/common/MotionEvent.aidl
new file mode 100644
index 0000000..dfea703
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/MotionEvent.aidl
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+import android.hardware.input.common.Action;
+import android.hardware.input.common.Button;
+import android.hardware.input.common.EdgeFlag;
+import android.hardware.input.common.Flag;
+import android.hardware.input.common.Meta;
+import android.hardware.input.common.PointerCoords;
+import android.hardware.input.common.PointerProperties;
+import android.hardware.input.common.PolicyFlag;
+import android.hardware.input.common.Source;
+import android.hardware.input.common.VideoFrame;
+
+/**
+ * Analogous to Android's native MotionEvent / NotifyMotionArgs.
+ * Stores the basic information about pointer movements.
+ */
+@VintfStability
+parcelable MotionEvent {
+    /**
+     * The id of the device which produced this event.
+     */
+    int deviceId;
+    /**
+     * The source type of this event.
+     */
+    Source source;
+    /**
+     * The display id associated with this event.
+     */
+    int displayId;
+    /**
+     * Time when the initial touch down occurred, in nanoseconds.
+     */
+    long downTime;
+    /**
+     * Time when this event occurred, in nanoseconds.
+     */
+    long eventTime;
+    /**
+     * The kind of action being performed.
+     */
+    Action action;
+    /**
+     * For ACTION_POINTER_DOWN or ACTION_POINTER_UP, this contains the associated pointer index.
+     * The index may be used to get information about the pointer that has gone down or up.
+     */
+    byte actionIndex;
+    /**
+     * The button that has been modified during a press or release action.
+     */
+    Button actionButton;
+    /**
+     * The motion event flags.
+     */
+    Flag flags;
+    /**
+     * The motion event policy flags.
+     */
+    PolicyFlag policyFlags;
+    /**
+     * The edges, if any, that were touched by this motion event.
+     */
+    EdgeFlag edgeFlags;
+    /**
+     * The state of any meta / modifier keys that were in effect when the event was generated.
+     */
+    Meta metaState;
+    /**
+     * The state of buttons that are pressed.
+     */
+    Button buttonState;
+    /**
+     * The precision of the X coordinate being reported.
+     */
+    float xPrecision;
+    /**
+     * The precision of the Y coordinate being reported.
+     */
+    float yPrecision;
+    /**
+     * The properties of each pointer present in this motion event.
+     */
+    PointerProperties[] pointerProperties;
+    /**
+     * The coordinates of each pointer.
+     */
+    PointerCoords[] pointerCoords;
+    /**
+     * Device time at which the event occurred, in microseconds.
+     * Will wrap after a little over an hour.
+     */
+    int deviceTimestamp;
+    /**
+     * The video frames, if any, associated with the current or previous motion events.
+     */
+    VideoFrame[] frames;
+}
diff --git a/input/common/aidl/android/hardware/input/common/PointerCoords.aidl b/input/common/aidl/android/hardware/input/common/PointerCoords.aidl
new file mode 100644
index 0000000..56d9a74
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/PointerCoords.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+import android.hardware.input.common.Axis;
+
+/**
+ * Pointer coordinate data. Analogous to Android's PointerCoords.
+ */
+@VintfStability
+parcelable PointerCoords {
+    /**
+     * Bitfield of axes that are present in this structure.
+     * Each bit position matches an axis defined in Axis.aidl.
+     */
+    long bits;
+    /**
+     * The values corresponding to each non-zero axis. This vector only
+     * contains non-zero entries. If an axis that is not currently specified
+     * in "bits" is requested, a zero value is returned.
+     * There are only as many values stored here
+     * as there are non-zero bits in the "bits" field.
+     * The values are position-packed. So the first non-zero axis will be
+     * at position 0, the next non-zero axis will be at position 1, and so on.
+     */
+    float[] values;
+}
diff --git a/input/common/aidl/android/hardware/input/common/PointerProperties.aidl b/input/common/aidl/android/hardware/input/common/PointerProperties.aidl
new file mode 100644
index 0000000..38d815e
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/PointerProperties.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+import android.hardware.input.common.ToolType;
+
+/**
+ * Properties of a particular pointer. Analogous to Android's PointerProperties.
+ */
+@VintfStability
+parcelable PointerProperties {
+    /**
+     * A number identifying a specific pointer. When a pointer is lifted,
+     * this value may be reused by another new pointer, even during the
+     * same gesture. For example, if there are two pointers touching the screen
+     * at the same time, they might have pointer ID's of 0 and 1. If the
+     * pointer with id = 0 is lifted, while the pointer with id = 1 remains, and
+     * a new pointer is placed on the screen, then the new pointer may receive
+     * an id of 0. While a pointer is active, it is guaranteed to keep the same
+     * id.
+     */
+    int id;
+    /**
+     * Type of tool used to make contact, such as a finger or stylus, if known.
+     */
+    ToolType toolType;
+}
diff --git a/input/common/aidl/android/hardware/input/common/PolicyFlag.aidl b/input/common/aidl/android/hardware/input/common/PolicyFlag.aidl
new file mode 100644
index 0000000..c5edd0d
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/PolicyFlag.aidl
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+/**
+ * Policy flags.
+ * The values 1 << 4 through 1 << 23 are not currently used.
+ * When a new value is added, make sure it matches a value defined in Input.h
+ * and other relevant files in frameworks/base and frameworks/native.
+ */
+@VintfStability
+@Backing(type="int")
+enum PolicyFlag {
+    /**
+     * Event should wake the device
+     */
+    WAKE = 1 << 0,
+    /**
+     * Key is virtual, and should generate haptic feedback
+     */
+    VIRTUAL = 1 << 1,
+    /**
+     * Key is the special function modifier
+     */
+    FUNCTION = 1 << 2,
+    /**
+     * Key represents a special gesture that has been detected
+     * by the touch firmware or driver.
+     */
+    GESTURE = 1 << 3,
+    /**
+     * Event was injected
+     */
+    INJECTED = 1 << 24,
+    /**
+     * Event comes from a trusted source, such as a directly attached input
+     * device or an application with system-wide event injection permission.
+     */
+    TRUSTED = 1 << 25,
+    /**
+     * Event has passed through an input filter.
+     */
+    FILTERED = 1 << 26,
+    /**
+     * Disable automatic key repeating behaviour.
+     */
+    DISABLE_KEY_REPEAT = 1 << 27,
+    /**
+     * Device was in an interactive state when the event was intercepted
+     */
+    INTERACTIVE = 1 << 29,
+    /**
+     * Event should be dispatched to applications
+     */
+    PASS_TO_USER = 1 << 30,
+}
diff --git a/input/common/aidl/android/hardware/input/common/Source.aidl b/input/common/aidl/android/hardware/input/common/Source.aidl
new file mode 100644
index 0000000..7eb6d66
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/Source.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+import android.hardware.input.common.SourceClass;
+
+/**
+ * Input sources
+ */
+@VintfStability
+@Backing(type="int")
+enum Source {
+    UNKNOWN = 0,
+    KEYBOARD = (1 << 8) | SourceClass.BUTTON,
+    DPAD = (1 << 9) | SourceClass.BUTTON,
+    GAMEPAD = (1 << 10) | SourceClass.BUTTON,
+    TOUCHSCREEN = (1 << 12) | SourceClass.POINTER,
+    MOUSE = (1 << 13) | SourceClass.POINTER,
+    STYLUS = (1 << 14) | SourceClass.POINTER,
+    BLUETOOTH_STYLUS = (1 << 15) | STYLUS,
+    TRACKBALL = (1 << 16) | SourceClass.NAVIGATION,
+    MOUSE_RELATIVE = (1 << 17) | SourceClass.NAVIGATION,
+    TOUCHPAD = (1 << 20) | SourceClass.POSITION,
+    TOUCH_NAVIGATION = (1 << 21) | SourceClass.NONE,
+    ROTARY_ENCODER = (1 << 22) | SourceClass.NONE,
+    JOYSTICK = (1 << 24) | SourceClass.JOYSTICK,
+    SENSOR = (1 << 26) | SourceClass.NONE,
+    ANY = 0xFFFFFF00,
+}
diff --git a/input/common/aidl/android/hardware/input/common/SourceClass.aidl b/input/common/aidl/android/hardware/input/common/SourceClass.aidl
new file mode 100644
index 0000000..4315798
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/SourceClass.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+@VintfStability
+@Backing(type="byte")
+enum SourceClass {
+    NONE = 0 << 0,
+    BUTTON = 1 << 0,
+    POINTER = 1 << 1,
+    NAVIGATION = 1 << 2,
+    POSITION = 1 << 3,
+    JOYSTICK = 1 << 4,
+}
diff --git a/input/common/aidl/android/hardware/input/common/ToolType.aidl b/input/common/aidl/android/hardware/input/common/ToolType.aidl
new file mode 100644
index 0000000..cfa057d
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/ToolType.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+/**
+ * Tool type of a pointer
+ */
+@VintfStability
+@Backing(type="byte")
+enum ToolType {
+    UNKNOWN = 0,
+    FINGER = 1,
+    STYLUS = 2,
+    MOUSE = 3,
+    ERASER = 4,
+}
diff --git a/input/common/aidl/android/hardware/input/common/VideoFrame.aidl b/input/common/aidl/android/hardware/input/common/VideoFrame.aidl
new file mode 100644
index 0000000..409cee5
--- /dev/null
+++ b/input/common/aidl/android/hardware/input/common/VideoFrame.aidl
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.common;
+
+/**
+ * Touch heatmap.
+ *
+ * The array is a 2-D row-major matrix with dimensions (height, width).
+ * The heatmap data is rotated when device orientation changes.
+ *
+ * Example:
+ *
+ * If the data in the array is:
+ * data[i] = i for i in 0 .. 59,
+ * then it can be represented as a 10 x 6 matrix:
+ *
+ *  <--   width   -->
+ *   0  1  2  3  4  5   ^
+ *   6  7  8  9 10 11   |
+ *  12 13 14 15 16 17   |
+ *  18    ...      23   |
+ *  24    ...      29   | height
+ *  30    ...      35   |
+ *  36    ...      41   |
+ *  42    ...      47   |
+ *  48    ...      53   |
+ *  54    ...      59   v
+ *
+ * Looking at the device in standard portrait orientation,
+ * the element "0" is the top left of the screen,
+ * "5" is at the top right, and "59" is the bottom right.
+ * Here height=10 and width=6.
+ *
+ * If the screen orientation changes to landscape (a 90 degree orientation
+ * change), the frame's dimensions will become 6 x 10
+ * and the data will look as follows:
+ * 54 48 42 36 30 24 18 12  6  0     ^
+ * ...                  13  7  1     |
+ * ...                  14  8  2     | height
+ * ...                  15  9  3     |
+ * ...                  16 10  4     |
+ * 59 53 47 41 35 29 23 17 11  5     v
+ * <--        width          -->
+ *
+ * Here the element "0" is at the physical top left of the unrotated screen.
+ *
+ * Since the coordinates of a MotionEvent are also adjusted based on the
+ * orientation, the rotation of the video frame data ensures that
+ * the axes for MotionEvent and VideoFrame data are consistent.
+ */
+@VintfStability
+parcelable VideoFrame {
+    /**
+     * Video frame data.
+     * Size of the data is height * width.
+     */
+    char[] data;
+    int height;
+    int width;
+    /**
+     * Time at which the frame was collected, in nanoseconds.
+     * Measured with the same clock that is used to populate MotionEvent times.
+     */
+    long timestamp;
+}
diff --git a/ir/aidl/Android.bp b/ir/aidl/Android.bp
index a623491..5dbf68f 100644
--- a/ir/aidl/Android.bp
+++ b/ir/aidl/Android.bp
@@ -35,8 +35,7 @@
         },
         ndk: {
             vndk: {
-                // TODO(b/206116595) enable this
-                enabled: false,
+                enabled: true,
             },
         },
     },
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/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 7676147..6412f3a 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -1712,6 +1712,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.
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/Device.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
index 0a6ca3e..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
@@ -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,
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 bdb5b54..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
@@ -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.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/Device.cpp b/neuralnetworks/1.0/utils/src/Device.cpp
index b0c236e..620d040 100644
--- a/neuralnetworks/1.0/utils/src/Device.cpp
+++ b/neuralnetworks/1.0/utils/src/Device.cpp
@@ -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 =
diff --git a/neuralnetworks/1.0/utils/src/PreparedModel.cpp b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
index 00e7d22..b8055fc 100644
--- a/neuralnetworks/1.0/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
@@ -59,7 +59,9 @@
 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;
@@ -94,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/test/DeviceTest.cpp b/neuralnetworks/1.0/utils/test/DeviceTest.cpp
index 83e555f..9e9db16 100644
--- a/neuralnetworks/1.0/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.0/utils/test/DeviceTest.cpp
@@ -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.1/utils/include/nnapi/hal/1.1/Device.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
index d6bd36a..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
@@ -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/src/Device.cpp b/neuralnetworks/1.1/utils/src/Device.cpp
index 3effa84..28f3276 100644
--- a/neuralnetworks/1.1/utils/src/Device.cpp
+++ b/neuralnetworks/1.1/utils/src/Device.cpp
@@ -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 =
diff --git a/neuralnetworks/1.1/utils/test/DeviceTest.cpp b/neuralnetworks/1.1/utils/test/DeviceTest.cpp
index 2248da6..8ab87bc 100644
--- a/neuralnetworks/1.1/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.1/utils/test/DeviceTest.cpp
@@ -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.2/utils/include/nnapi/hal/1.2/Burst.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Burst.h
index ac9411c..1b28476 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Burst.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Burst.h
@@ -170,13 +170,16 @@
     // 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;
+            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 override;
+            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
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 c3348aa..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);
@@ -78,7 +78,7 @@
         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);
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 e7ac172..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
@@ -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/PreparedModel.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
index 1150e5e..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
@@ -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/src/Burst.cpp b/neuralnetworks/1.2/utils/src/Burst.cpp
index 911fbfa..23e8070 100644
--- a/neuralnetworks/1.2/utils/src/Burst.cpp
+++ b/neuralnetworks/1.2/utils/src/Burst.cpp
@@ -305,8 +305,9 @@
 
 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 {
     // 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
@@ -317,7 +318,7 @@
     // 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);
+        return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration, {}, {});
     }
 
     // ensure that request is ready for IPC
@@ -346,7 +347,7 @@
     // 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 kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration, {}, {});
     };
     return executeInternal(requestPacket, relocation, fallback);
 }
@@ -354,14 +355,17 @@
 // 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 {
+        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);
+        return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration, {},
+                                                       {});
     }
 
     // ensure that request is ready for IPC
diff --git a/neuralnetworks/1.2/utils/src/Conversions.cpp b/neuralnetworks/1.2/utils/src/Conversions.cpp
index 838d9c4..62ec2ed 100644
--- a/neuralnetworks/1.2/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.2/utils/src/Conversions.cpp
@@ -212,9 +212,9 @@
     };
 }
 
-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,
     };
@@ -495,7 +495,7 @@
 }
 
 nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
-        const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+        const nn::ExtensionNameAndPrefix& extensionNameAndPrefix) {
     return Model::ExtensionNameAndPrefix{
             .name = extensionNameAndPrefix.name,
             .prefix = extensionNameAndPrefix.prefix,
diff --git a/neuralnetworks/1.2/utils/src/Device.cpp b/neuralnetworks/1.2/utils/src/Device.cpp
index e7acecd..3a58d2c 100644
--- a/neuralnetworks/1.2/utils/src/Device.cpp
+++ b/neuralnetworks/1.2/utils/src/Device.cpp
@@ -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 =
diff --git a/neuralnetworks/1.2/utils/src/PreparedModel.cpp b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
index 6df3df3..feb3951 100644
--- a/neuralnetworks/1.2/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
@@ -91,7 +91,9 @@
 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;
@@ -123,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;
diff --git a/neuralnetworks/1.2/utils/test/DeviceTest.cpp b/neuralnetworks/1.2/utils/test/DeviceTest.cpp
index 1dc6285..0d8c141 100644
--- a/neuralnetworks/1.2/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.2/utils/test/DeviceTest.cpp
@@ -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.3/utils/include/nnapi/hal/1.3/Device.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
index c3c6fc4..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
@@ -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 480438d..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
@@ -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/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
index a1d414c..09e9d80 100644
--- a/neuralnetworks/1.3/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -396,7 +396,7 @@
 }
 
 nn::GeneralResult<V1_2::Model::ExtensionNameAndPrefix> unvalidatedConvert(
-        const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+        const nn::ExtensionNameAndPrefix& extensionNameAndPrefix) {
     return V1_2::utils::unvalidatedConvert(extensionNameAndPrefix);
 }
 
diff --git a/neuralnetworks/1.3/utils/src/Device.cpp b/neuralnetworks/1.3/utils/src/Device.cpp
index 9517fda..824cec6 100644
--- a/neuralnetworks/1.3/utils/src/Device.cpp
+++ b/neuralnetworks/1.3/utils/src/Device.cpp
@@ -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 =
diff --git a/neuralnetworks/1.3/utils/src/PreparedModel.cpp b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
index ce977e5..b92f877 100644
--- a/neuralnetworks/1.3/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
@@ -135,8 +135,9 @@
 
 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;
@@ -174,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;
@@ -230,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;
diff --git a/neuralnetworks/1.3/utils/test/DeviceTest.cpp b/neuralnetworks/1.3/utils/test/DeviceTest.cpp
index 7eba4bc..6f48837 100644
--- a/neuralnetworks/1.3/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.3/utils/test/DeviceTest.cpp
@@ -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/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionConfig.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionConfig.aidl
index 295fde9..cb85743 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionConfig.aidl
@@ -31,12 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.neuralnetworks;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+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/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IExecution.aidl
similarity index 84%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IExecution.aidl
index 295fde9..ab5275e 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IExecution.aidl
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.neuralnetworks;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+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/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PrepareModelConfig.aidl
similarity index 78%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PrepareModelConfig.aidl
index 295fde9..85c924f 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PrepareModelConfig.aidl
@@ -31,12 +31,15 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.neuralnetworks;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+parcelable PrepareModelConfig {
+  android.hardware.neuralnetworks.ExecutionPreference preference;
+  android.hardware.neuralnetworks.Priority priority;
+  long deadlineNs;
+  ParcelFileDescriptor[] modelCache;
+  ParcelFileDescriptor[] dataCache;
+  byte[] cacheToken;
+  android.hardware.neuralnetworks.TokenValuePair[] compilationHints;
+  android.hardware.neuralnetworks.ExtensionNameAndPrefix[] extensionNameToPrefix;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/TokenValuePair.aidl
similarity index 89%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
copy to neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/TokenValuePair.aidl
index 295fde9..e477d6e 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/TokenValuePair.aidl
@@ -31,12 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.neuralnetworks;
 @VintfStability
-parcelable SensorLocation {
-  int displayId;
-  int sensorLocationX;
-  int sensorLocationY;
-  int sensorRadius;
-  String display = "";
+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..821b9fe 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;
 
 /**
@@ -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..949804e 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,86 @@
      *     - 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.
+     *
+     * @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.
+     *
+     * @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.
+     *
+     * @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/PrepareModelConfig.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/PrepareModelConfig.aidl
new file mode 100644
index 0000000..96df968
--- /dev/null
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/PrepareModelConfig.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.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 {
+    /**
+     * 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 IDevice::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[] 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 e356104..3faa613 100644
--- a/neuralnetworks/aidl/utils/Android.bp
+++ b/neuralnetworks/aidl/utils/Android.bp
@@ -26,7 +26,14 @@
 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"],
@@ -47,6 +54,7 @@
     },
 }
 
+// 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"],
@@ -56,19 +64,25 @@
 }
 
 cc_library_static {
-    name: "neuralnetworks_utils_hal_aidl_v2",
-    defaults: ["neuralnetworks_utils_hal_aidl_defaults"],
-    shared_libs: [
-        "android.hardware.neuralnetworks-V2-ndk",
-    ],
-}
-
-cc_library_static {
     name: "neuralnetworks_utils_hal_aidl",
     defaults: ["neuralnetworks_utils_hal_aidl_defaults"],
-    shared_libs: [
-        "android.hardware.neuralnetworks-V3-ndk",
+    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
@@ -79,9 +93,10 @@
     static_libs: [
         "android.hardware.common-V2-ndk",
         "android.hardware.graphics.common-V3-ndk",
-        "android.hardware.neuralnetworks-V3-ndk",
+        "android.hardware.neuralnetworks-V4-ndk",
         "neuralnetworks_utils_hal_aidl",
     ],
+    cflags: ["-DNN_AIDL_V4_OR_ABOVE"],
 }
 
 cc_test {
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 168264b..960be2b 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Callbacks.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Callbacks.h
@@ -36,6 +36,8 @@
   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;
 
@@ -44,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 477b311..af58715 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h
@@ -46,6 +46,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 +78,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);
@@ -97,6 +101,10 @@
         const aidl_hal::ExtensionOperandTypeInformation& operandTypeInformation);
 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);
 
@@ -116,6 +124,14 @@
 
 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(
@@ -152,7 +168,7 @@
 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);
@@ -166,6 +182,10 @@
 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);
@@ -190,6 +210,13 @@
 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);
 
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
index d558f66..615c6de 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
@@ -42,6 +42,7 @@
     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, nn::Version featureLevel);
 
@@ -67,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,
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
index 3fb443c..cacdc26 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h
@@ -61,6 +61,13 @@
 #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;
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/Utils.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
index a27487e..beca38b 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
@@ -38,6 +38,8 @@
             return nn::kVersionFeatureLevel6;
         case 3:
             return nn::kVersionFeatureLevel7;
+        case 4:
+            return nn::kVersionFeatureLevel8;
         default:
             return std::nullopt;
     }
diff --git a/neuralnetworks/aidl/utils/src/Burst.cpp b/neuralnetworks/aidl/utils/src/Burst.cpp
index fb00b26..6c7aa88 100644
--- a/neuralnetworks/aidl/utils/src/Burst.cpp
+++ b/neuralnetworks/aidl/utils/src/Burst.cpp
@@ -43,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(
@@ -64,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;
 };
@@ -149,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);
 }
 
@@ -170,8 +179,9 @@
 
 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;
@@ -200,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();
@@ -221,9 +231,21 @@
     }
 
     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>{});
@@ -241,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;
@@ -272,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) {
@@ -286,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)),
@@ -300,6 +329,8 @@
       kMemoryIdentifierTokens(std::move(memoryIdentifierTokens)),
       kMeasure(measure),
       kLoopTimeoutDuration(loopTimeoutDuration),
+      kHints(hints),
+      kExtensionNameToPrefix(extensionNameToPrefix),
       kRelocation(std::move(relocation)),
       kCacheHolds(std::move(cacheHolds)) {}
 
@@ -307,7 +338,8 @@
         const nn::OptionalTimePoint& deadline) const {
     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 8084970..554f3fa 100644
--- a/neuralnetworks/aidl/utils/src/Callbacks.cpp
+++ b/neuralnetworks/aidl/utils/src/Callbacks.cpp
@@ -38,16 +38,17 @@
 // 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) {
+        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));
+    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 113d2da..eb28db7 100644
--- a/neuralnetworks/aidl/utils/src/Conversions.cpp
+++ b/neuralnetworks/aidl/utils/src/Conversions.cpp
@@ -302,9 +302,9 @@
     };
 }
 
-GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
+GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
         const aidl_hal::ExtensionNameAndPrefix& extensionNameAndPrefix) {
-    return Model::ExtensionNameAndPrefix{
+    return ExtensionNameAndPrefix{
             .name = extensionNameAndPrefix.name,
             .prefix = extensionNameAndPrefix.prefix,
     };
@@ -506,6 +506,12 @@
     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);
 }
@@ -562,6 +568,17 @@
 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) {
@@ -942,7 +959,7 @@
 }
 
 nn::GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
-        const nn::Model::ExtensionNameAndPrefix& extensionNameToPrefix) {
+        const nn::ExtensionNameAndPrefix& extensionNameToPrefix) {
     return ExtensionNameAndPrefix{
             .name = extensionNameToPrefix.name,
             .prefix = extensionNameToPrefix.prefix,
@@ -1055,6 +1072,11 @@
     return Extension{.name = extension.name,
                      .operandTypes = NN_TRY(unvalidatedConvert(extension.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);
@@ -1134,6 +1156,17 @@
         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);
diff --git a/neuralnetworks/aidl/utils/src/Device.cpp b/neuralnetworks/aidl/utils/src/Device.cpp
index 5b7ec4e..f3f4fdb 100644
--- a/neuralnetworks/aidl/utils/src/Device.cpp
+++ b/neuralnetworks/aidl/utils/src/Device.cpp
@@ -215,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 =
@@ -225,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));
+    auto aidlModelCache = NN_TRY(convert(modelCache));
+    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());
 
+    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), aidlToken, std::move(aidlHints),
+                 std::move(aidlExtensionPrefix)},
+                cb);
+        HANDLE_ASTATUS(ret) << "prepareModel failed";
+        return cb->get();
+    }
     const auto ret = kDevice->prepareModel(aidlModel, aidlPreference, aidlPriority, aidlDeadline,
                                            aidlModelCache, aidlDataCache, aidlToken, cb);
     HANDLE_ASTATUS(ret) << "prepareModel failed";
-
     return cb->get();
 }
 
@@ -247,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 94edd90..2fd88af 100644
--- a/neuralnetworks/aidl/utils/src/Execution.cpp
+++ b/neuralnetworks/aidl/utils/src/Execution.cpp
@@ -35,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 {
+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/InvalidDevice.cpp b/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
index c9d9955..33270ff 100644
--- a/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
+++ b/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
@@ -167,6 +167,31 @@
     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, 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 f25c2c8..7e3a31c 100644
--- a/neuralnetworks/aidl/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/aidl/utils/src/PreparedModel.cpp
@@ -54,61 +54,16 @@
     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::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,
-                           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(convertExecutionResults(executionResult.outputShapes, executionResult.timing));
+            NN_TRY(convertExecutionResults(result.outputShapes, result.timing));
 
     if (relocation.output) {
         relocation.output->flush();
@@ -117,44 +72,8 @@
 }
 
 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::SyncFence::create(NN_TRY(nn::convert(result.syncFence))).value();
@@ -165,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({});
@@ -189,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;
@@ -202,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 {
@@ -218,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/test/DeviceTest.cpp b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
index 0366e7d..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,26 +158,7 @@
     return ndk::ScopedAStatus::fromStatus(STATUS_DEAD_OBJECT);
 };
 
-class DeviceTest : public ::testing::TestWithParam<nn::Version> {
-  protected:
-    const nn::Version kVersion = GetParam();
-};
-
-std::string printDeviceTest(const testing::TestParamInfo<nn::Version>& info) {
-    const nn::Version version = info.param;
-    CHECK(!version.runtimeOnlyFeatures);
-    switch (version.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";
-        default:
-            LOG(FATAL) << "Invalid AIDL version: " << version;
-            return "invalid";
-    }
-}
+class DeviceTest : public VersionedAidlUtilsTestBase {};
 
 }  // namespace
 
@@ -578,6 +571,8 @@
 }
 
 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, kVersion).value();
@@ -589,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())
@@ -598,6 +593,8 @@
 }
 
 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, kVersion).value();
@@ -608,7 +605,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());
@@ -616,6 +613,8 @@
 }
 
 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, kVersion).value();
@@ -626,7 +625,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());
@@ -634,6 +633,8 @@
 }
 
 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, kVersion).value();
@@ -644,7 +645,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());
@@ -652,6 +653,8 @@
 }
 
 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, kVersion).value();
@@ -661,7 +664,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());
@@ -669,6 +672,8 @@
 }
 
 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, kVersion).value();
@@ -678,7 +683,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());
@@ -686,6 +691,8 @@
 }
 
 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, kVersion).value();
@@ -699,7 +706,157 @@
 
     // 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_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, 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());
@@ -894,9 +1051,6 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-INSTANTIATE_TEST_SUITE_P(TestDevice, DeviceTest,
-                         ::testing::Values(nn::kVersionFeatureLevel5, nn::kVersionFeatureLevel6,
-                                           nn::kVersionFeatureLevel7),
-                         printDeviceTest);
+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/MockBurst.h b/neuralnetworks/aidl/utils/test/MockBurst.h
index 5083bbd..4cf60b6 100644
--- a/neuralnetworks/aidl/utils/test/MockBurst.h
+++ b/neuralnetworks/aidl/utils/test/MockBurst.h
@@ -32,6 +32,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..216f569
--- /dev/null
+++ b/neuralnetworks/aidl/utils/test/MockExecution.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_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>
+#include <hidl/HidlSupport.h>
+#include <hidl/Status.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/MockPreparedModel.h b/neuralnetworks/aidl/utils/test/MockPreparedModel.h
index a4ae2b7..318acc2 100644
--- a/neuralnetworks/aidl/utils/test/MockPreparedModel.h
+++ b/neuralnetworks/aidl/utils/test/MockPreparedModel.h
@@ -17,6 +17,7 @@
 #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>
@@ -39,8 +40,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/functional/GeneratedTestHarness.cpp b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
index f67fd34..8c8a87a 100644
--- a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
@@ -58,25 +58,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 {
@@ -558,209 +599,266 @@
         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
+                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(-1);
+                    }
                 }
+
+                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) {
+                    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 +868,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: {
@@ -812,8 +919,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 +948,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 +986,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 cd5475c..97760ae 100644
--- a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
@@ -204,10 +204,27 @@
         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));
+    }
 };
 
 template <typename... Args>
diff --git a/neuralnetworks/aidl/vts/functional/Utils.cpp b/neuralnetworks/aidl/vts/functional/Utils.cpp
index 325a436..efd5bca 100644
--- a/neuralnetworks/aidl/vts/functional/Utils.cpp
+++ b/neuralnetworks/aidl/vts/functional/Utils.cpp
@@ -177,6 +177,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..0db3f8c 100644
--- a/neuralnetworks/aidl/vts/functional/Utils.h
+++ b/neuralnetworks/aidl/vts/functional/Utils.h
@@ -111,6 +111,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 fdc7eff..931ba25 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, {}, {}, kEmptyCacheToken, {}, {}},
+            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) {
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..ad93e6d 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
@@ -41,7 +41,8 @@
 
 // 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 +57,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,
+                                                {},
+                                                {},
+                                                kEmptyCacheToken,
+                                                {},
+                                                {}},
+                                               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();
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/adapter/aidl/include/nnapi/hal/aidl/Burst.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Burst.h
index f2687c4..8d42e2f 100644
--- a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Burst.h
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Burst.h
@@ -46,6 +46,11 @@
                                             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 {
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Device.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Device.h
index aa29d63..c94f270 100644
--- a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Device.h
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Device.h
@@ -31,6 +31,7 @@
 #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>
@@ -72,6 +73,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;
 
   protected:
     const ::android::nn::SharedDevice kDevice;
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
index 93e0427..d1359d6 100644
--- a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/PreparedModel.h
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/PreparedModel.h
@@ -23,6 +23,7 @@
 #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>
@@ -50,6 +51,17 @@
                                      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;
 
diff --git a/neuralnetworks/utils/adapter/aidl/src/Burst.cpp b/neuralnetworks/utils/adapter/aidl/src/Burst.cpp
index 4fabb20..a4a80fa 100644
--- a/neuralnetworks/utils/adapter/aidl/src/Burst.cpp
+++ b/neuralnetworks/utils/adapter/aidl/src/Burst.cpp
@@ -93,7 +93,8 @@
 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) {
+        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()";
@@ -107,11 +108,13 @@
     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);
+    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();
@@ -155,7 +158,24 @@
                                                ExecutionResult* executionResult) {
     auto result =
             adapter::executeSynchronously(*kBurst, kMemoryCache, request, memoryIdentifierTokens,
-                                          measureTiming, deadlineNs, loopTimeoutDurationNs);
+                                          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);
diff --git a/neuralnetworks/utils/adapter/aidl/src/Device.cpp b/neuralnetworks/utils/adapter/aidl/src/Device.cpp
index 763be7f..84aaddb 100644
--- a/neuralnetworks/utils/adapter/aidl/src/Device.cpp
+++ b/neuralnetworks/utils/adapter/aidl/src/Device.cpp
@@ -148,13 +148,14 @@
     }
 }
 
-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::shared_ptr<IPreparedModelCallback>& callback) {
+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";
     }
@@ -166,12 +167,16 @@
     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, callback] {
-        auto result = device->prepareModel(nnModel, nnPreference, nnPriority, nnDeadline,
-                                           nnModelCache, nnDataCache, nnToken);
+                 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);
@@ -273,8 +278,9 @@
                                         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);
+    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);
@@ -301,4 +307,21 @@
     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, 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);
+        callback->notify(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
index 71ed1a8..790558f 100644
--- a/neuralnetworks/utils/adapter/aidl/src/PreparedModel.cpp
+++ b/neuralnetworks/utils/adapter/aidl/src/PreparedModel.cpp
@@ -17,6 +17,7 @@
 #include "PreparedModel.h"
 
 #include "Burst.h"
+#include "Execution.h"
 
 #include <aidl/android/hardware/neuralnetworks/BnFencedExecutionCallback.h>
 #include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
@@ -26,6 +27,7 @@
 #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>
@@ -116,17 +118,20 @@
     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) {
+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);
+            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();
@@ -145,16 +150,76 @@
 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) {
+        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));
+            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()) {
@@ -179,7 +244,7 @@
                                                        int64_t loopTimeoutDurationNs,
                                                        ExecutionResult* executionResult) {
     auto result = adapter::executeSynchronously(*kPreparedModel, request, measureTiming, deadlineNs,
-                                                loopTimeoutDurationNs);
+                                                loopTimeoutDurationNs, {}, {});
     if (!result.has_value()) {
         const auto& [message, code, _] = result.error();
         const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
@@ -195,7 +260,41 @@
         bool measureTiming, int64_t deadlineNs, int64_t loopTimeoutDurationNs, int64_t durationNs,
         FencedExecutionResult* executionResult) {
     auto result = adapter::executeFenced(*kPreparedModel, request, waitFor, measureTiming,
-                                         deadlineNs, loopTimeoutDurationNs, durationNs);
+                                         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);
@@ -222,4 +321,51 @@
     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/src/Burst.cpp b/neuralnetworks/utils/adapter/hidl/src/Burst.cpp
index 8b2e1dd..e3b165b 100644
--- a/neuralnetworks/utils/adapter/hidl/src/Burst.cpp
+++ b/neuralnetworks/utils/adapter/hidl/src/Burst.cpp
@@ -250,7 +250,7 @@
     nn::MeasureTiming canonicalMeasure = NN_TRY(nn::convert(measure));
 
     const auto [outputShapes, timing] =
-            NN_TRY(mBurstExecutor->execute(canonicalRequest, canonicalMeasure, {}, {}));
+            NN_TRY(mBurstExecutor->execute(canonicalRequest, canonicalMeasure, {}, {}, {}, {}));
 
     return std::make_pair(NN_TRY(V1_2::utils::convert(outputShapes)),
                           NN_TRY(V1_2::utils::convert(timing)));
diff --git a/neuralnetworks/utils/adapter/hidl/src/Device.cpp b/neuralnetworks/utils/adapter/hidl/src/Device.cpp
index 4993a80..0f44638 100644
--- a/neuralnetworks/utils/adapter/hidl/src/Device.cpp
+++ b/neuralnetworks/utils/adapter/hidl/src/Device.cpp
@@ -135,7 +135,7 @@
 
     Task task = [device, nnModel = std::move(nnModel), executor, callback] {
         auto result = device->prepareModel(nnModel, nn::ExecutionPreference::DEFAULT,
-                                           nn::Priority::DEFAULT, {}, {}, {}, {});
+                                           nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
         notify(callback.get(), std::move(result), executor);
     };
     executor(std::move(task), {});
@@ -155,8 +155,8 @@
     const auto nnPreference = NN_TRY(convertInput(preference));
 
     Task task = [device, nnModel = std::move(nnModel), nnPreference, executor, callback] {
-        auto result =
-                device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {}, {}, {}, {});
+        auto result = device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {}, {}, {},
+                                           {}, {}, {});
         notify(callback.get(), std::move(result), executor);
     };
     executor(std::move(task), {});
@@ -185,7 +185,7 @@
                  nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
                  nnToken, executor, callback] {
         auto result = device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {},
-                                           nnModelCache, nnDataCache, nnToken);
+                                           nnModelCache, nnDataCache, nnToken, {}, {});
         notify(callback.get(), std::move(result), executor);
     };
     executor(std::move(task), {});
@@ -215,7 +215,7 @@
                  nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
                  nnToken, executor, callback] {
         auto result = device->prepareModel(nnModel, nnPreference, nnPriority, nnDeadline,
-                                           nnModelCache, nnDataCache, nnToken);
+                                           nnModelCache, nnDataCache, nnToken, {}, {});
         notify(callback.get(), std::move(result), executor);
     };
     executor(std::move(task), nnDeadline);
diff --git a/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp b/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp
index 71060d5..c6055a6 100644
--- a/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp
+++ b/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp
@@ -159,7 +159,7 @@
     }
 
     Task task = [preparedModel, nnRequest = std::move(nnRequest), callback] {
-        auto result = preparedModel->execute(nnRequest, nn::MeasureTiming::NO, {}, {});
+        auto result = preparedModel->execute(nnRequest, nn::MeasureTiming::NO, {}, {}, {}, {});
         notify(callback.get(), std::move(result));
     };
     executor(std::move(task), {});
@@ -185,7 +185,7 @@
     }
 
     Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, callback] {
-        auto result = preparedModel->execute(nnRequest, nnMeasure, {}, {});
+        auto result = preparedModel->execute(nnRequest, nnMeasure, {}, {}, {}, {});
         notify(callback.get(), std::move(result));
     };
     executor(std::move(task), {});
@@ -216,8 +216,8 @@
 
     Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, nnDeadline,
                  nnLoopTimeoutDuration, callback] {
-        auto result =
-                preparedModel->execute(nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration);
+        auto result = preparedModel->execute(nnRequest, nnMeasure, nnDeadline,
+                                             nnLoopTimeoutDuration, {}, {});
         notify(callback.get(), std::move(result));
     };
     executor(std::move(task), nnDeadline);
@@ -232,7 +232,7 @@
     const auto nnMeasure = NN_TRY(convertInput(measure));
 
     const auto [outputShapes, timing] =
-            NN_TRY(preparedModel->execute(nnRequest, nnMeasure, {}, {}));
+            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));
@@ -248,8 +248,8 @@
     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));
+    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));
@@ -293,8 +293,9 @@
     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 [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);
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/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/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/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 0488b63..d9b8505 100644
--- a/neuralnetworks/utils/common/test/ResilientDeviceTest.cpp
+++ b/neuralnetworks/utils/common/test/ResilientDeviceTest.cpp
@@ -309,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())
@@ -324,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());
@@ -339,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());
@@ -355,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())
@@ -679,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/radio/1.5/vts/functional/radio_hidl_hal_api.cpp b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
index d108951..152858f 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -1271,8 +1271,12 @@
     EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
 
     int32_t firstApiLevel = android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
+    int32_t boardApiLevel = android::base::GetIntProperty<int32_t>("ro.board.first_api_level", 0);
     // Allow devices shipping with Radio::1_5 and Android 11 to not support barring info.
-    if (firstApiLevel > 0 && firstApiLevel <= 30) {
+    // b/212384410 Some GRF targets lauched with S release but with vendor R release
+    // do not support getBarringInfo API. Allow these devices to not support barring info.
+    if ((firstApiLevel > 0 && firstApiLevel <= 30) ||
+        (boardApiLevel > 0 && boardApiLevel <= 30)) {
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
                                      {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
         // Early exit for devices that don't support barring info.
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
index 6982d40..980b042 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
@@ -47,4 +47,7 @@
   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/IRadioDataIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
index b0cc1eb..0ffa1f7 100644
--- 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
@@ -38,4 +38,5 @@
   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/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
index e780d8e..ae103fc 100644
--- a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
@@ -73,4 +73,16 @@
      * 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/IRadioDataIndication.aidl b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
index 1772c88..938c695 100644
--- a/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
+++ b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
@@ -21,6 +21,7 @@
 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.
@@ -72,4 +73,17 @@
      * @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/compat/libradiocompat/data/RadioIndication-data.cpp b/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
index 1d367d2..602bb39 100644
--- a/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
+++ b/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
@@ -85,4 +85,11 @@
     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/include/libradiocompat/RadioIndication.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
index c668af5..6cfd59c 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
@@ -186,6 +186,8 @@
             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,
diff --git a/radio/aidl/vts/radio_data_indication.cpp b/radio/aidl/vts/radio_data_indication.cpp
index 4d3c539..61e079e 100644
--- a/radio/aidl/vts/radio_data_indication.cpp
+++ b/radio/aidl/vts/radio_data_indication.cpp
@@ -37,3 +37,8 @@
                                                       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_utils.h b/radio/aidl/vts/radio_data_utils.h
index 50c7878..fb91ef6 100644
--- a/radio/aidl/vts/radio_data_utils.h
+++ b/radio/aidl/vts/radio_data_utils.h
@@ -95,6 +95,8 @@
 
     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.
diff --git a/security/dice/aidl/Android.bp b/security/dice/aidl/Android.bp
index af9dd33..01bc91e 100644
--- a/security/dice/aidl/Android.bp
+++ b/security/dice/aidl/Android.bp
@@ -41,6 +41,10 @@
         },
         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/BccHandover.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/BccHandover.aidl
index ab50c36..8baca94 100644
--- 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
@@ -35,7 +35,7 @@
 /* @hide */
 @RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable BccHandover {
-  byte[] cdiAttest;
-  byte[] cdiSeal;
+  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/InputValues.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/InputValues.aidl
index 79583fb..e43c429 100644
--- 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
@@ -35,10 +35,10 @@
 /* @hide */
 @RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable InputValues {
-  byte[] codeHash;
+  byte[64] codeHash;
   android.hardware.security.dice.Config config;
-  byte[] authorityHash;
+  byte[64] authorityHash;
   @nullable byte[] authorityDescriptor;
   android.hardware.security.dice.Mode mode = android.hardware.security.dice.Mode.NOT_INITIALIZED;
-  byte[] hidden;
+  byte[64] hidden;
 }
diff --git a/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl b/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl
index d522cef..6ca862c 100644
--- a/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl
+++ b/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl
@@ -27,13 +27,13 @@
 @RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
 parcelable BccHandover {
     /**
-     * CDI_attest. Must a exactly 32 bytes of data.
+     * CDI_attest. Must be exactly 32 bytes of data.
      */
-    byte[] cdiAttest;
+    byte[32] cdiAttest;
     /**
-     * CDI_seal. Must a exactly 32 bytes of data.
+     * CDI_seal. Must be exactly 32 bytes of data.
      */
-    byte[] cdiSeal;
+    byte[32] cdiSeal;
     /**
      * CBOR encoded BCC.
      *
diff --git a/security/dice/aidl/android/hardware/security/dice/InputValues.aidl b/security/dice/aidl/android/hardware/security/dice/InputValues.aidl
index e44ef22..711d523 100644
--- a/security/dice/aidl/android/hardware/security/dice/InputValues.aidl
+++ b/security/dice/aidl/android/hardware/security/dice/InputValues.aidl
@@ -34,7 +34,7 @@
     /**
      * The target code hash. Must be exactly 64 bytes.
      */
-    byte[] codeHash;
+    byte[64] codeHash;
     /**
      * The configuration data.
      */
@@ -42,7 +42,7 @@
     /**
      * The authority hash. Must be exactly 64 bytes. Must be all zero if unused.
      */
-    byte[] authorityHash;
+    byte[64] authorityHash;
     /**
      * Optional free form authorityDescriptor.
      */
@@ -54,5 +54,5 @@
     /**
      * Optional hidden values. Must be exactly 64 bytes. Must be all zero if unused.
      */
-    byte[] hidden;
+    byte[64] hidden;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index ce83044..ca89555 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -227,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 --
      *
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 02462fc..374f2da 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -812,6 +812,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,
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index dd3719b..340010f 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -4608,8 +4608,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);
@@ -4633,7 +4635,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));
     }
@@ -5818,8 +5820,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());
@@ -5979,8 +5981,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());
@@ -6002,7 +6006,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));
@@ -6033,6 +6037,7 @@
                                 .Authorization(TAG_NONCE, iv);
 
     for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
+        SCOPED_TRACE(testing::Message() << "i = " << i);
         ++ciphertext[ciphertext.size() / 2];
         EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
         string plaintext;
diff --git a/sensors/aidl/Android.bp b/sensors/aidl/Android.bp
index 7324abf..92b7ad0 100644
--- a/sensors/aidl/Android.bp
+++ b/sensors/aidl/Android.bp
@@ -1,3 +1,12 @@
+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.sensors",
     vendor_available: true,
diff --git a/sensors/aidl/default/multihal/Android.bp b/sensors/aidl/default/multihal/Android.bp
index a7f6af2..eee1062 100644
--- a/sensors/aidl/default/multihal/Android.bp
+++ b/sensors/aidl/default/multihal/Android.bp
@@ -43,6 +43,7 @@
     export_include_dirs: ["include"],
     srcs: [
         "HalProxyAidl.cpp",
+        "ConvertUtils.cpp",
     ],
     visibility: [
         ":__subpackages__",
diff --git a/sensors/aidl/default/multihal/ConvertUtils.cpp b/sensors/aidl/default/multihal/ConvertUtils.cpp
new file mode 100644
index 0000000..509bbb0
--- /dev/null
+++ b/sensors/aidl/default/multihal/ConvertUtils.cpp
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ConvertUtils.h"
+#include <android-base/logging.h>
+#include <log/log.h>
+
+using AidlSensorInfo = ::aidl::android::hardware::sensors::SensorInfo;
+using AidlSensorType = ::aidl::android::hardware::sensors::SensorType;
+using AidlEvent = ::aidl::android::hardware::sensors::Event;
+using AidlSensorStatus = ::aidl::android::hardware::sensors::SensorStatus;
+using ::aidl::android::hardware::sensors::AdditionalInfo;
+using ::aidl::android::hardware::sensors::DynamicSensorInfo;
+using ::android::hardware::sensors::V1_0::MetaDataEventType;
+using V1_0SensorStatus = ::android::hardware::sensors::V1_0::SensorStatus;
+using ::android::hardware::sensors::V1_0::AdditionalInfoType;
+using V2_1SensorInfo = ::android::hardware::sensors::V2_1::SensorInfo;
+using V2_1Event = ::android::hardware::sensors::V2_1::Event;
+using V2_1SensorType = ::android::hardware::sensors::V2_1::SensorType;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace implementation {
+
+AidlSensorInfo convertSensorInfo(const V2_1SensorInfo& sensorInfo) {
+    AidlSensorInfo aidlSensorInfo;
+    aidlSensorInfo.sensorHandle = sensorInfo.sensorHandle;
+    aidlSensorInfo.name = sensorInfo.name;
+    aidlSensorInfo.vendor = sensorInfo.vendor;
+    aidlSensorInfo.version = sensorInfo.version;
+    aidlSensorInfo.type = (AidlSensorType)sensorInfo.type;
+    aidlSensorInfo.typeAsString = sensorInfo.typeAsString;
+    aidlSensorInfo.maxRange = sensorInfo.maxRange;
+    aidlSensorInfo.resolution = sensorInfo.resolution;
+    aidlSensorInfo.power = sensorInfo.power;
+    aidlSensorInfo.minDelayUs = sensorInfo.minDelay;
+    aidlSensorInfo.fifoReservedEventCount = sensorInfo.fifoReservedEventCount;
+    aidlSensorInfo.fifoMaxEventCount = sensorInfo.fifoMaxEventCount;
+    aidlSensorInfo.requiredPermission = sensorInfo.requiredPermission;
+    aidlSensorInfo.maxDelayUs = sensorInfo.maxDelay;
+    aidlSensorInfo.flags = sensorInfo.flags;
+    return aidlSensorInfo;
+}
+
+void convertToHidlEvent(const AidlEvent& aidlEvent, V2_1Event* hidlEvent) {
+    hidlEvent->timestamp = aidlEvent.timestamp;
+    hidlEvent->sensorHandle = aidlEvent.sensorHandle;
+    hidlEvent->sensorType = (V2_1SensorType)aidlEvent.sensorType;
+
+    switch (aidlEvent.sensorType) {
+        case AidlSensorType::META_DATA:
+            hidlEvent->u.meta.what =
+                    (MetaDataEventType)aidlEvent.payload.get<Event::EventPayload::meta>().what;
+            break;
+        case AidlSensorType::ACCELEROMETER:
+        case AidlSensorType::MAGNETIC_FIELD:
+        case AidlSensorType::ORIENTATION:
+        case AidlSensorType::GYROSCOPE:
+        case AidlSensorType::GRAVITY:
+        case AidlSensorType::LINEAR_ACCELERATION:
+            hidlEvent->u.vec3.x = aidlEvent.payload.get<Event::EventPayload::vec3>().x;
+            hidlEvent->u.vec3.y = aidlEvent.payload.get<Event::EventPayload::vec3>().y;
+            hidlEvent->u.vec3.z = aidlEvent.payload.get<Event::EventPayload::vec3>().z;
+            break;
+        case AidlSensorType::GAME_ROTATION_VECTOR:
+            hidlEvent->u.vec4.x = aidlEvent.payload.get<Event::EventPayload::vec4>().x;
+            hidlEvent->u.vec4.y = aidlEvent.payload.get<Event::EventPayload::vec4>().y;
+            hidlEvent->u.vec4.z = aidlEvent.payload.get<Event::EventPayload::vec4>().z;
+            hidlEvent->u.vec4.w = aidlEvent.payload.get<Event::EventPayload::vec4>().w;
+            break;
+        case AidlSensorType::ROTATION_VECTOR:
+        case AidlSensorType::GEOMAGNETIC_ROTATION_VECTOR:
+            std::copy(aidlEvent.payload.get<Event::EventPayload::data>().values.data(),
+                      aidlEvent.payload.get<Event::EventPayload::data>().values.data() + 5,
+                      hidlEvent->u.data.data());
+            break;
+        case AidlSensorType::ACCELEROMETER_UNCALIBRATED:
+        case AidlSensorType::MAGNETIC_FIELD_UNCALIBRATED:
+        case AidlSensorType::GYROSCOPE_UNCALIBRATED:
+            hidlEvent->u.uncal.x = aidlEvent.payload.get<Event::EventPayload::uncal>().x;
+            hidlEvent->u.uncal.y = aidlEvent.payload.get<Event::EventPayload::uncal>().y;
+            hidlEvent->u.uncal.z = aidlEvent.payload.get<Event::EventPayload::uncal>().z;
+            hidlEvent->u.uncal.x_bias = aidlEvent.payload.get<Event::EventPayload::uncal>().xBias;
+            hidlEvent->u.uncal.y_bias = aidlEvent.payload.get<Event::EventPayload::uncal>().yBias;
+            hidlEvent->u.uncal.z_bias = aidlEvent.payload.get<Event::EventPayload::uncal>().zBias;
+            break;
+        case AidlSensorType::DEVICE_ORIENTATION:
+        case AidlSensorType::LIGHT:
+        case AidlSensorType::PRESSURE:
+        case AidlSensorType::PROXIMITY:
+        case AidlSensorType::RELATIVE_HUMIDITY:
+        case AidlSensorType::AMBIENT_TEMPERATURE:
+        case AidlSensorType::SIGNIFICANT_MOTION:
+        case AidlSensorType::STEP_DETECTOR:
+        case AidlSensorType::TILT_DETECTOR:
+        case AidlSensorType::WAKE_GESTURE:
+        case AidlSensorType::GLANCE_GESTURE:
+        case AidlSensorType::PICK_UP_GESTURE:
+        case AidlSensorType::WRIST_TILT_GESTURE:
+        case AidlSensorType::STATIONARY_DETECT:
+        case AidlSensorType::MOTION_DETECT:
+        case AidlSensorType::HEART_BEAT:
+        case AidlSensorType::LOW_LATENCY_OFFBODY_DETECT:
+        case AidlSensorType::HINGE_ANGLE:
+            hidlEvent->u.scalar = aidlEvent.payload.get<Event::EventPayload::scalar>();
+            break;
+        case AidlSensorType::STEP_COUNTER:
+            hidlEvent->u.stepCount = aidlEvent.payload.get<AidlEvent::EventPayload::stepCount>();
+            break;
+        case AidlSensorType::HEART_RATE:
+            hidlEvent->u.heartRate.bpm =
+                    aidlEvent.payload.get<AidlEvent::EventPayload::heartRate>().bpm;
+            hidlEvent->u.heartRate.status =
+                    (V1_0SensorStatus)aidlEvent.payload.get<Event::EventPayload::heartRate>()
+                            .status;
+            break;
+        case AidlSensorType::POSE_6DOF:
+            std::copy(std::begin(aidlEvent.payload.get<AidlEvent::EventPayload::pose6DOF>().values),
+                      std::end(aidlEvent.payload.get<AidlEvent::EventPayload::pose6DOF>().values),
+                      hidlEvent->u.pose6DOF.data());
+            break;
+        case AidlSensorType::DYNAMIC_SENSOR_META:
+            hidlEvent->u.dynamic.connected =
+                    aidlEvent.payload.get<Event::EventPayload::dynamic>().connected;
+            hidlEvent->u.dynamic.sensorHandle =
+                    aidlEvent.payload.get<Event::EventPayload::dynamic>().sensorHandle;
+            std::copy(
+                    std::begin(
+                            aidlEvent.payload.get<AidlEvent::EventPayload::dynamic>().uuid.values),
+                    std::end(aidlEvent.payload.get<AidlEvent::EventPayload::dynamic>().uuid.values),
+                    hidlEvent->u.dynamic.uuid.data());
+            break;
+        case AidlSensorType::ADDITIONAL_INFO: {
+            const AdditionalInfo& additionalInfo =
+                    aidlEvent.payload.get<AidlEvent::EventPayload::additional>();
+            hidlEvent->u.additional.type = (AdditionalInfoType)additionalInfo.type;
+            hidlEvent->u.additional.serial = additionalInfo.serial;
+
+            switch (additionalInfo.payload.getTag()) {
+                case AdditionalInfo::AdditionalInfoPayload::Tag::dataInt32: {
+                    const auto& aidlData =
+                            additionalInfo.payload
+                                    .get<AdditionalInfo::AdditionalInfoPayload::dataInt32>()
+                                    .values;
+                    std::copy(std::begin(aidlData), std::end(aidlData),
+                              hidlEvent->u.additional.u.data_int32.data());
+                    break;
+                }
+                case AdditionalInfo::AdditionalInfoPayload::Tag::dataFloat: {
+                    const auto& aidlData =
+                            additionalInfo.payload
+                                    .get<AdditionalInfo::AdditionalInfoPayload::dataFloat>()
+                                    .values;
+                    std::copy(std::begin(aidlData), std::end(aidlData),
+                              hidlEvent->u.additional.u.data_float.data());
+                    break;
+                }
+                default:
+                    ALOGE("Invalid sensor additioanl info tag: %d",
+                          additionalInfo.payload.getTag());
+                    break;
+            }
+            break;
+        }
+        default:
+            CHECK_GE((int32_t)aidlEvent.sensorType, (int32_t)SensorType::DEVICE_PRIVATE_BASE);
+            std::copy(std::begin(aidlEvent.payload.get<AidlEvent::EventPayload::data>().values),
+                      std::end(aidlEvent.payload.get<AidlEvent::EventPayload::data>().values),
+                      hidlEvent->u.data.data());
+            break;
+    }
+}
+
+void convertToAidlEvent(const V2_1Event& hidlEvent, AidlEvent* aidlEvent) {
+    aidlEvent->timestamp = hidlEvent.timestamp;
+    aidlEvent->sensorHandle = hidlEvent.sensorHandle;
+    aidlEvent->sensorType = (AidlSensorType)hidlEvent.sensorType;
+    switch (hidlEvent.sensorType) {
+        case V2_1SensorType::META_DATA: {
+            AidlEvent::EventPayload::MetaData meta;
+            meta.what = (Event::EventPayload::MetaData::MetaDataEventType)hidlEvent.u.meta.what;
+            aidlEvent->payload.set<Event::EventPayload::meta>(meta);
+            break;
+        }
+        case V2_1SensorType::ACCELEROMETER:
+        case V2_1SensorType::MAGNETIC_FIELD:
+        case V2_1SensorType::ORIENTATION:
+        case V2_1SensorType::GYROSCOPE:
+        case V2_1SensorType::GRAVITY:
+        case V2_1SensorType::LINEAR_ACCELERATION: {
+            AidlEvent::EventPayload::Vec3 vec3;
+            vec3.x = hidlEvent.u.vec3.x;
+            vec3.y = hidlEvent.u.vec3.y;
+            vec3.z = hidlEvent.u.vec3.z;
+            aidlEvent->payload.set<Event::EventPayload::vec3>(vec3);
+            break;
+        }
+        case V2_1SensorType::GAME_ROTATION_VECTOR: {
+            AidlEvent::EventPayload::Vec4 vec4;
+            vec4.x = hidlEvent.u.vec4.x;
+            vec4.y = hidlEvent.u.vec4.y;
+            vec4.z = hidlEvent.u.vec4.z;
+            vec4.w = hidlEvent.u.vec4.w;
+            aidlEvent->payload.set<Event::EventPayload::vec4>(vec4);
+            break;
+        }
+        case V2_1SensorType::ROTATION_VECTOR:
+        case V2_1SensorType::GEOMAGNETIC_ROTATION_VECTOR: {
+            AidlEvent::EventPayload::Data data;
+            std::copy(hidlEvent.u.data.data(), hidlEvent.u.data.data() + 5,
+                      std::begin(data.values));
+            aidlEvent->payload.set<Event::EventPayload::data>(data);
+            break;
+        }
+        case V2_1SensorType::MAGNETIC_FIELD_UNCALIBRATED:
+        case V2_1SensorType::GYROSCOPE_UNCALIBRATED:
+        case V2_1SensorType::ACCELEROMETER_UNCALIBRATED: {
+            AidlEvent::EventPayload::Uncal uncal;
+            uncal.x = hidlEvent.u.uncal.x;
+            uncal.y = hidlEvent.u.uncal.y;
+            uncal.z = hidlEvent.u.uncal.z;
+            uncal.xBias = hidlEvent.u.uncal.x_bias;
+            uncal.yBias = hidlEvent.u.uncal.y_bias;
+            uncal.zBias = hidlEvent.u.uncal.z_bias;
+            aidlEvent->payload.set<Event::EventPayload::uncal>(uncal);
+            break;
+        }
+        case V2_1SensorType::DEVICE_ORIENTATION:
+        case V2_1SensorType::LIGHT:
+        case V2_1SensorType::PRESSURE:
+        case V2_1SensorType::PROXIMITY:
+        case V2_1SensorType::RELATIVE_HUMIDITY:
+        case V2_1SensorType::AMBIENT_TEMPERATURE:
+        case V2_1SensorType::SIGNIFICANT_MOTION:
+        case V2_1SensorType::STEP_DETECTOR:
+        case V2_1SensorType::TILT_DETECTOR:
+        case V2_1SensorType::WAKE_GESTURE:
+        case V2_1SensorType::GLANCE_GESTURE:
+        case V2_1SensorType::PICK_UP_GESTURE:
+        case V2_1SensorType::WRIST_TILT_GESTURE:
+        case V2_1SensorType::STATIONARY_DETECT:
+        case V2_1SensorType::MOTION_DETECT:
+        case V2_1SensorType::HEART_BEAT:
+        case V2_1SensorType::LOW_LATENCY_OFFBODY_DETECT:
+        case V2_1SensorType::HINGE_ANGLE:
+            aidlEvent->payload.set<Event::EventPayload::scalar>(hidlEvent.u.scalar);
+            break;
+        case V2_1SensorType::STEP_COUNTER:
+            aidlEvent->payload.set<Event::EventPayload::stepCount>(hidlEvent.u.stepCount);
+            break;
+        case V2_1SensorType::HEART_RATE: {
+            AidlEvent::EventPayload::HeartRate heartRate;
+            heartRate.bpm = hidlEvent.u.heartRate.bpm;
+            heartRate.status = (SensorStatus)hidlEvent.u.heartRate.status;
+            aidlEvent->payload.set<Event::EventPayload::heartRate>(heartRate);
+            break;
+        }
+        case V2_1SensorType::POSE_6DOF: {
+            AidlEvent::EventPayload::Pose6Dof pose6Dof;
+            std::copy(hidlEvent.u.pose6DOF.data(),
+                      hidlEvent.u.pose6DOF.data() + hidlEvent.u.pose6DOF.size(),
+                      std::begin(pose6Dof.values));
+            aidlEvent->payload.set<Event::EventPayload::pose6DOF>(pose6Dof);
+            break;
+        }
+        case V2_1SensorType::DYNAMIC_SENSOR_META: {
+            DynamicSensorInfo dynamicSensorInfo;
+            dynamicSensorInfo.connected = hidlEvent.u.dynamic.connected;
+            dynamicSensorInfo.sensorHandle = hidlEvent.u.dynamic.sensorHandle;
+            std::copy(hidlEvent.u.dynamic.uuid.data(),
+                      hidlEvent.u.dynamic.uuid.data() + hidlEvent.u.dynamic.uuid.size(),
+                      std::begin(dynamicSensorInfo.uuid.values));
+            aidlEvent->payload.set<Event::EventPayload::dynamic>(dynamicSensorInfo);
+            break;
+        }
+        case V2_1SensorType::ADDITIONAL_INFO: {
+            AdditionalInfo additionalInfo;
+            additionalInfo.type = (AdditionalInfo::AdditionalInfoType)hidlEvent.u.additional.type;
+            additionalInfo.serial = hidlEvent.u.additional.serial;
+
+            AdditionalInfo::AdditionalInfoPayload::Int32Values int32Values;
+            std::copy(hidlEvent.u.additional.u.data_int32.data(),
+                      hidlEvent.u.additional.u.data_int32.data() +
+                              hidlEvent.u.additional.u.data_int32.size(),
+                      std::begin(int32Values.values));
+            additionalInfo.payload.set<AdditionalInfo::AdditionalInfoPayload::dataInt32>(
+                    int32Values);
+            aidlEvent->payload.set<Event::EventPayload::additional>(additionalInfo);
+            break;
+        }
+        default: {
+            CHECK_GE((int32_t)hidlEvent.sensorType, (int32_t)V2_1SensorType::DEVICE_PRIVATE_BASE);
+            AidlEvent::EventPayload::Data data;
+            std::copy(hidlEvent.u.data.data(), hidlEvent.u.data.data() + hidlEvent.u.data.size(),
+                      std::begin(data.values));
+            aidlEvent->payload.set<Event::EventPayload::data>(data);
+            break;
+        }
+    }
+}
+
+}  // namespace implementation
+}  // namespace sensors
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/sensors/aidl/default/multihal/include/ConvertUtils.h b/sensors/aidl/default/multihal/include/ConvertUtils.h
index 09ec0dc..91dfabd 100644
--- a/sensors/aidl/default/multihal/include/ConvertUtils.h
+++ b/sensors/aidl/default/multihal/include/ConvertUtils.h
@@ -16,7 +16,8 @@
 
 #pragma once
 
-#include <android-base/logging.h>
+#include <aidl/android/hardware/sensors/BnSensors.h>
+#include <android/hardware/sensors/2.1/types.h>
 
 namespace aidl {
 namespace android {
@@ -24,396 +25,23 @@
 namespace sensors {
 namespace implementation {
 
-static ::aidl::android::hardware::sensors::SensorInfo convertSensorInfo(
-        const ::android::hardware::sensors::V2_1::SensorInfo& sensorInfo) {
-    ::aidl::android::hardware::sensors::SensorInfo aidlSensorInfo;
-    aidlSensorInfo.sensorHandle = sensorInfo.sensorHandle;
-    aidlSensorInfo.name = sensorInfo.name;
-    aidlSensorInfo.vendor = sensorInfo.vendor;
-    aidlSensorInfo.version = sensorInfo.version;
-    aidlSensorInfo.type = (::aidl::android::hardware::sensors::SensorType)sensorInfo.type;
-    aidlSensorInfo.typeAsString = sensorInfo.typeAsString;
-    aidlSensorInfo.maxRange = sensorInfo.maxRange;
-    aidlSensorInfo.resolution = sensorInfo.resolution;
-    aidlSensorInfo.power = sensorInfo.power;
-    aidlSensorInfo.minDelayUs = sensorInfo.minDelay;
-    aidlSensorInfo.fifoReservedEventCount = sensorInfo.fifoReservedEventCount;
-    aidlSensorInfo.fifoMaxEventCount = sensorInfo.fifoMaxEventCount;
-    aidlSensorInfo.requiredPermission = sensorInfo.requiredPermission;
-    aidlSensorInfo.maxDelayUs = sensorInfo.maxDelay;
-    aidlSensorInfo.flags = sensorInfo.flags;
-    return aidlSensorInfo;
-}
+/**
+ * Generates an AIDL SensorInfo instance from the passed HIDL V2.1 SensorInfo instance.
+ */
+::aidl::android::hardware::sensors::SensorInfo convertSensorInfo(
+        const ::android::hardware::sensors::V2_1::SensorInfo& sensorInfo);
 
-static void convertToHidlEvent(const ::aidl::android::hardware::sensors::Event& aidlEvent,
-                               ::android::hardware::sensors::V2_1::Event* hidlEvent) {
-    hidlEvent->timestamp = aidlEvent.timestamp;
-    hidlEvent->sensorHandle = aidlEvent.sensorHandle;
-    hidlEvent->sensorType = (::android::hardware::sensors::V2_1::SensorType)aidlEvent.sensorType;
+/**
+ * Populates a HIDL V2.1 Event instance based on an AIDL Event instance.
+ */
+void convertToHidlEvent(const ::aidl::android::hardware::sensors::Event& aidlEvent,
+                        ::android::hardware::sensors::V2_1::Event* hidlEvent);
 
-    switch (aidlEvent.sensorType) {
-        case ::aidl::android::hardware::sensors::SensorType::META_DATA:
-            hidlEvent->u.meta.what =
-                    (::android::hardware::sensors::V1_0::MetaDataEventType)aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::meta>()
-                            .what;
-            break;
-        case ::aidl::android::hardware::sensors::SensorType::ACCELEROMETER:
-        case ::aidl::android::hardware::sensors::SensorType::MAGNETIC_FIELD:
-        case ::aidl::android::hardware::sensors::SensorType::ORIENTATION:
-        case ::aidl::android::hardware::sensors::SensorType::GYROSCOPE:
-        case ::aidl::android::hardware::sensors::SensorType::GRAVITY:
-        case ::aidl::android::hardware::sensors::SensorType::LINEAR_ACCELERATION:
-            hidlEvent->u.vec3.x =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::vec3>()
-                            .x;
-            hidlEvent->u.vec3.y =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::vec3>()
-                            .y;
-            hidlEvent->u.vec3.z =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::vec3>()
-                            .z;
-            break;
-        case ::aidl::android::hardware::sensors::SensorType::GAME_ROTATION_VECTOR:
-            hidlEvent->u.vec4.x =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::vec4>()
-                            .x;
-            hidlEvent->u.vec4.y =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::vec4>()
-                            .y;
-            hidlEvent->u.vec4.z =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::vec4>()
-                            .z;
-            hidlEvent->u.vec4.w =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::vec4>()
-                            .w;
-            break;
-        case ::aidl::android::hardware::sensors::SensorType::ROTATION_VECTOR:
-        case ::aidl::android::hardware::sensors::SensorType::GEOMAGNETIC_ROTATION_VECTOR:
-            std::copy(aidlEvent.payload
-                              .get<::aidl::android::hardware::sensors::Event::EventPayload::data>()
-                              .values.data(),
-                      aidlEvent.payload
-                                      .get<::aidl::android::hardware::sensors::Event::EventPayload::
-                                                   data>()
-                                      .values.data() +
-                              5,
-                      hidlEvent->u.data.data());
-            break;
-        case ::aidl::android::hardware::sensors::SensorType::ACCELEROMETER_UNCALIBRATED:
-        case ::aidl::android::hardware::sensors::SensorType::MAGNETIC_FIELD_UNCALIBRATED:
-        case ::aidl::android::hardware::sensors::SensorType::GYROSCOPE_UNCALIBRATED:
-            hidlEvent->u.uncal.x =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::uncal>()
-                            .x;
-            hidlEvent->u.uncal.y =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::uncal>()
-                            .y;
-            hidlEvent->u.uncal.z =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::uncal>()
-                            .z;
-            hidlEvent->u.uncal.x_bias =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::uncal>()
-                            .xBias;
-            hidlEvent->u.uncal.y_bias =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::uncal>()
-                            .yBias;
-            hidlEvent->u.uncal.z_bias =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::uncal>()
-                            .zBias;
-            break;
-        case ::aidl::android::hardware::sensors::SensorType::DEVICE_ORIENTATION:
-        case ::aidl::android::hardware::sensors::SensorType::LIGHT:
-        case ::aidl::android::hardware::sensors::SensorType::PRESSURE:
-        case ::aidl::android::hardware::sensors::SensorType::PROXIMITY:
-        case ::aidl::android::hardware::sensors::SensorType::RELATIVE_HUMIDITY:
-        case ::aidl::android::hardware::sensors::SensorType::AMBIENT_TEMPERATURE:
-        case ::aidl::android::hardware::sensors::SensorType::SIGNIFICANT_MOTION:
-        case ::aidl::android::hardware::sensors::SensorType::STEP_DETECTOR:
-        case ::aidl::android::hardware::sensors::SensorType::TILT_DETECTOR:
-        case ::aidl::android::hardware::sensors::SensorType::WAKE_GESTURE:
-        case ::aidl::android::hardware::sensors::SensorType::GLANCE_GESTURE:
-        case ::aidl::android::hardware::sensors::SensorType::PICK_UP_GESTURE:
-        case ::aidl::android::hardware::sensors::SensorType::WRIST_TILT_GESTURE:
-        case ::aidl::android::hardware::sensors::SensorType::STATIONARY_DETECT:
-        case ::aidl::android::hardware::sensors::SensorType::MOTION_DETECT:
-        case ::aidl::android::hardware::sensors::SensorType::HEART_BEAT:
-        case ::aidl::android::hardware::sensors::SensorType::LOW_LATENCY_OFFBODY_DETECT:
-        case ::aidl::android::hardware::sensors::SensorType::HINGE_ANGLE:
-            hidlEvent->u.scalar =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::scalar>();
-            break;
-        case ::aidl::android::hardware::sensors::SensorType::STEP_COUNTER:
-            hidlEvent->u.stepCount = aidlEvent.payload.get<
-                    ::aidl::android::hardware::sensors::Event::EventPayload::stepCount>();
-            break;
-        case ::aidl::android::hardware::sensors::SensorType::HEART_RATE:
-            hidlEvent->u.heartRate.bpm = aidlEvent.payload
-                                                 .get<::aidl::android::hardware::sensors::Event::
-                                                              EventPayload::heartRate>()
-                                                 .bpm;
-            hidlEvent->u.heartRate.status =
-                    (::android::hardware::sensors::V1_0::SensorStatus)aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::
-                                         heartRate>()
-                            .status;
-            break;
-        case ::aidl::android::hardware::sensors::SensorType::POSE_6DOF:
-            std::copy(std::begin(aidlEvent.payload
-                                         .get<::aidl::android::hardware::sensors::Event::
-                                                      EventPayload::pose6DOF>()
-                                         .values),
-                      std::end(aidlEvent.payload
-                                       .get<::aidl::android::hardware::sensors::Event::
-                                                    EventPayload::data>()
-                                       .values),
-                      hidlEvent->u.pose6DOF.data());
-            break;
-        case ::aidl::android::hardware::sensors::SensorType::DYNAMIC_SENSOR_META:
-            hidlEvent->u.dynamic.connected =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::dynamic>()
-                            .connected;
-            hidlEvent->u.dynamic.sensorHandle =
-                    aidlEvent.payload
-                            .get<::aidl::android::hardware::sensors::Event::EventPayload::dynamic>()
-                            .sensorHandle;
-            std::copy(std::begin(aidlEvent.payload
-                                         .get<::aidl::android::hardware::sensors::Event::
-                                                      EventPayload::dynamic>()
-                                         .uuid.values),
-                      std::end(aidlEvent.payload
-                                       .get<::aidl::android::hardware::sensors::Event::
-                                                    EventPayload::dynamic>()
-                                       .uuid.values),
-                      hidlEvent->u.dynamic.uuid.data());
-            break;
-        case ::aidl::android::hardware::sensors::SensorType::ADDITIONAL_INFO: {
-            const AdditionalInfo& additionalInfo = aidlEvent.payload.get<
-                    ::aidl::android::hardware::sensors::Event::EventPayload::additional>();
-            hidlEvent->u.additional.type =
-                    (::android::hardware::sensors::V1_0::AdditionalInfoType)additionalInfo.type;
-            hidlEvent->u.additional.serial = additionalInfo.serial;
-
-            switch (additionalInfo.payload.getTag()) {
-                case ::aidl::android::hardware::sensors::AdditionalInfo::AdditionalInfoPayload::
-                        Tag::dataInt32:
-                    std::copy(
-                            std::begin(additionalInfo.payload
-                                               .get<::aidl::android::hardware::sensors::
-                                                            AdditionalInfo::AdditionalInfoPayload::
-                                                                    dataInt32>()
-                                               .values),
-                            std::end(additionalInfo.payload
-                                             .get<::aidl::android::hardware::sensors::
-                                                          AdditionalInfo::AdditionalInfoPayload::
-                                                                  dataInt32>()
-                                             .values),
-                            hidlEvent->u.additional.u.data_int32.data());
-                    break;
-                case ::aidl::android::hardware::sensors::AdditionalInfo::AdditionalInfoPayload::
-                        Tag::dataFloat:
-                    std::copy(
-                            std::begin(additionalInfo.payload
-                                               .get<::aidl::android::hardware::sensors::
-                                                            AdditionalInfo::AdditionalInfoPayload::
-                                                                    dataFloat>()
-                                               .values),
-                            std::end(additionalInfo.payload
-                                             .get<::aidl::android::hardware::sensors::
-                                                          AdditionalInfo::AdditionalInfoPayload::
-                                                                  dataFloat>()
-                                             .values),
-                            hidlEvent->u.additional.u.data_float.data());
-                    break;
-                default:
-                    ALOGE("Invalid sensor additioanl info tag: %d",
-                          additionalInfo.payload.getTag());
-                    break;
-            }
-            break;
-        }
-        default:
-            CHECK_GE((int32_t)aidlEvent.sensorType,
-                     (int32_t)::aidl::android::hardware::sensors::SensorType::DEVICE_PRIVATE_BASE);
-            std::copy(std::begin(aidlEvent.payload
-                                         .get<::aidl::android::hardware::sensors::Event::
-                                                      EventPayload::data>()
-                                         .values),
-                      std::end(aidlEvent.payload
-                                       .get<::aidl::android::hardware::sensors::Event::
-                                                    EventPayload::data>()
-                                       .values),
-                      hidlEvent->u.data.data());
-            break;
-    }
-}
-
-static void convertToAidlEvent(const ::android::hardware::sensors::V2_1::Event& hidlEvent,
-                               ::aidl::android::hardware::sensors::Event* aidlEvent) {
-    aidlEvent->timestamp = hidlEvent.timestamp;
-    aidlEvent->sensorHandle = hidlEvent.sensorHandle;
-    aidlEvent->sensorType = (::aidl::android::hardware::sensors::SensorType)hidlEvent.sensorType;
-    switch (hidlEvent.sensorType) {
-        case ::android::hardware::sensors::V2_1::SensorType::META_DATA: {
-            ::aidl::android::hardware::sensors::Event::EventPayload::MetaData meta;
-            meta.what = (::aidl::android::hardware::sensors::Event::EventPayload::MetaData::
-                                 MetaDataEventType)hidlEvent.u.meta.what;
-            aidlEvent->payload.set<::aidl::android::hardware::sensors::Event::EventPayload::meta>(
-                    meta);
-            break;
-        }
-        case ::android::hardware::sensors::V2_1::SensorType::ACCELEROMETER:
-        case ::android::hardware::sensors::V2_1::SensorType::MAGNETIC_FIELD:
-        case ::android::hardware::sensors::V2_1::SensorType::ORIENTATION:
-        case ::android::hardware::sensors::V2_1::SensorType::GYROSCOPE:
-        case ::android::hardware::sensors::V2_1::SensorType::GRAVITY:
-        case ::android::hardware::sensors::V2_1::SensorType::LINEAR_ACCELERATION: {
-            ::aidl::android::hardware::sensors::Event::EventPayload::Vec3 vec3;
-            vec3.x = hidlEvent.u.vec3.x;
-            vec3.y = hidlEvent.u.vec3.y;
-            vec3.z = hidlEvent.u.vec3.z;
-            aidlEvent->payload.set<::aidl::android::hardware::sensors::Event::EventPayload::vec3>(
-                    vec3);
-            break;
-        }
-        case ::android::hardware::sensors::V2_1::SensorType::GAME_ROTATION_VECTOR: {
-            ::aidl::android::hardware::sensors::Event::EventPayload::Vec4 vec4;
-            vec4.x = hidlEvent.u.vec4.x;
-            vec4.y = hidlEvent.u.vec4.y;
-            vec4.z = hidlEvent.u.vec4.z;
-            vec4.w = hidlEvent.u.vec4.w;
-            aidlEvent->payload.set<::aidl::android::hardware::sensors::Event::EventPayload::vec4>(
-                    vec4);
-            break;
-        }
-        case ::android::hardware::sensors::V2_1::SensorType::ROTATION_VECTOR:
-        case ::android::hardware::sensors::V2_1::SensorType::GEOMAGNETIC_ROTATION_VECTOR: {
-            ::aidl::android::hardware::sensors::Event::EventPayload::Data data;
-            std::copy(hidlEvent.u.data.data(), hidlEvent.u.data.data() + 5,
-                      std::begin(data.values));
-            aidlEvent->payload.set<::aidl::android::hardware::sensors::Event::EventPayload::data>(
-                    data);
-            break;
-        }
-        case ::android::hardware::sensors::V2_1::SensorType::MAGNETIC_FIELD_UNCALIBRATED:
-        case ::android::hardware::sensors::V2_1::SensorType::GYROSCOPE_UNCALIBRATED:
-        case ::android::hardware::sensors::V2_1::SensorType::ACCELEROMETER_UNCALIBRATED: {
-            ::aidl::android::hardware::sensors::Event::EventPayload::Uncal uncal;
-            uncal.x = hidlEvent.u.uncal.x;
-            uncal.y = hidlEvent.u.uncal.y;
-            uncal.z = hidlEvent.u.uncal.z;
-            uncal.xBias = hidlEvent.u.uncal.x_bias;
-            uncal.yBias = hidlEvent.u.uncal.y_bias;
-            uncal.zBias = hidlEvent.u.uncal.z_bias;
-            aidlEvent->payload.set<::aidl::android::hardware::sensors::Event::EventPayload::uncal>(
-                    uncal);
-            break;
-        }
-        case ::android::hardware::sensors::V2_1::SensorType::DEVICE_ORIENTATION:
-        case ::android::hardware::sensors::V2_1::SensorType::LIGHT:
-        case ::android::hardware::sensors::V2_1::SensorType::PRESSURE:
-        case ::android::hardware::sensors::V2_1::SensorType::PROXIMITY:
-        case ::android::hardware::sensors::V2_1::SensorType::RELATIVE_HUMIDITY:
-        case ::android::hardware::sensors::V2_1::SensorType::AMBIENT_TEMPERATURE:
-        case ::android::hardware::sensors::V2_1::SensorType::SIGNIFICANT_MOTION:
-        case ::android::hardware::sensors::V2_1::SensorType::STEP_DETECTOR:
-        case ::android::hardware::sensors::V2_1::SensorType::TILT_DETECTOR:
-        case ::android::hardware::sensors::V2_1::SensorType::WAKE_GESTURE:
-        case ::android::hardware::sensors::V2_1::SensorType::GLANCE_GESTURE:
-        case ::android::hardware::sensors::V2_1::SensorType::PICK_UP_GESTURE:
-        case ::android::hardware::sensors::V2_1::SensorType::WRIST_TILT_GESTURE:
-        case ::android::hardware::sensors::V2_1::SensorType::STATIONARY_DETECT:
-        case ::android::hardware::sensors::V2_1::SensorType::MOTION_DETECT:
-        case ::android::hardware::sensors::V2_1::SensorType::HEART_BEAT:
-        case ::android::hardware::sensors::V2_1::SensorType::LOW_LATENCY_OFFBODY_DETECT:
-        case ::android::hardware::sensors::V2_1::SensorType::HINGE_ANGLE:
-            aidlEvent->payload.set<::aidl::android::hardware::sensors::Event::EventPayload::scalar>(
-                    hidlEvent.u.scalar);
-            break;
-        case ::android::hardware::sensors::V2_1::SensorType::STEP_COUNTER:
-            aidlEvent->payload
-                    .set<::aidl::android::hardware::sensors::Event::EventPayload::stepCount>(
-                            hidlEvent.u.stepCount);
-            break;
-        case ::android::hardware::sensors::V2_1::SensorType::HEART_RATE: {
-            ::aidl::android::hardware::sensors::Event::EventPayload::HeartRate heartRate;
-            heartRate.bpm = hidlEvent.u.heartRate.bpm;
-            heartRate.status =
-                    (::aidl::android::hardware::sensors::SensorStatus)hidlEvent.u.heartRate.status;
-            aidlEvent->payload
-                    .set<::aidl::android::hardware::sensors::Event::EventPayload::heartRate>(
-                            heartRate);
-            break;
-        }
-        case ::android::hardware::sensors::V2_1::SensorType::POSE_6DOF: {
-            ::aidl::android::hardware::sensors::Event::EventPayload::Pose6Dof pose6Dof;
-            std::copy(hidlEvent.u.pose6DOF.data(),
-                      hidlEvent.u.pose6DOF.data() + hidlEvent.u.pose6DOF.size(),
-                      std::begin(pose6Dof.values));
-            aidlEvent->payload
-                    .set<::aidl::android::hardware::sensors::Event::EventPayload::pose6DOF>(
-                            pose6Dof);
-            break;
-        }
-        case ::android::hardware::sensors::V2_1::SensorType::DYNAMIC_SENSOR_META: {
-            ::aidl::android::hardware::sensors::DynamicSensorInfo dynamicSensorInfo;
-            dynamicSensorInfo.connected = hidlEvent.u.dynamic.connected;
-            dynamicSensorInfo.sensorHandle = hidlEvent.u.dynamic.sensorHandle;
-            std::copy(hidlEvent.u.dynamic.uuid.data(),
-                      hidlEvent.u.dynamic.uuid.data() + hidlEvent.u.dynamic.uuid.size(),
-                      std::begin(dynamicSensorInfo.uuid.values));
-            aidlEvent->payload
-                    .set<::aidl::android::hardware::sensors::Event::EventPayload::dynamic>(
-                            dynamicSensorInfo);
-            break;
-        }
-        case ::android::hardware::sensors::V2_1::SensorType::ADDITIONAL_INFO: {
-            ::aidl::android::hardware::sensors::AdditionalInfo additionalInfo;
-            additionalInfo.type =
-                    (::aidl::android::hardware::sensors::AdditionalInfo::AdditionalInfoType)
-                            hidlEvent.u.additional.type;
-            additionalInfo.serial = hidlEvent.u.additional.serial;
-
-            ::aidl::android::hardware::sensors::AdditionalInfo::AdditionalInfoPayload::Int32Values
-                    int32Values;
-            std::copy(hidlEvent.u.additional.u.data_int32.data(),
-                      hidlEvent.u.additional.u.data_int32.data() +
-                              hidlEvent.u.additional.u.data_int32.size(),
-                      std::begin(int32Values.values));
-            additionalInfo.payload.set<::aidl::android::hardware::sensors::AdditionalInfo::
-                                               AdditionalInfoPayload::dataInt32>(int32Values);
-            aidlEvent->payload
-                    .set<::aidl::android::hardware::sensors::Event::EventPayload::additional>(
-                            additionalInfo);
-            break;
-        }
-        default: {
-            CHECK_GE((int32_t)hidlEvent.sensorType,
-                     (int32_t)::android::hardware::sensors::V2_1::SensorType::DEVICE_PRIVATE_BASE);
-            ::aidl::android::hardware::sensors::Event::EventPayload::Data data;
-            std::copy(hidlEvent.u.data.data(), hidlEvent.u.data.data() + hidlEvent.u.data.size(),
-                      std::begin(data.values));
-            aidlEvent->payload.set<::aidl::android::hardware::sensors::Event::EventPayload::data>(
-                    data);
-            break;
-        }
-    }
-}
+/**
+ * Populates an AIDL Event instance based on a HIDL V2.1 Event instance.
+ */
+void convertToAidlEvent(const ::android::hardware::sensors::V2_1::Event& hidlEvent,
+                        ::aidl::android::hardware::sensors::Event* aidlEvent);
 
 }  // namespace implementation
 }  // namespace sensors
diff --git a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
index 608a4b0..1bc7263 100644
--- a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
+++ b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
@@ -978,7 +978,7 @@
         ASSERT_EQ(status.getExceptionCode(), error);
         ASSERT_EQ(channelHandle, -1);
     }
-    directChannelHandle = &channelHandle;
+    *directChannelHandle = channelHandle;
 }
 
 void SensorsAidlTest::verifyUnregisterDirectChannel(int32_t* channelHandle,
diff --git a/wifi/1.5/default/hidl_struct_util.h b/wifi/1.5/default/hidl_struct_util.h
deleted file mode 100644
index 352f213..0000000
--- a/wifi/1.5/default/hidl_struct_util.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HIDL_STRUCT_UTIL_H_
-#define HIDL_STRUCT_UTIL_H_
-
-#include <vector>
-
-#include <android/hardware/wifi/1.0/IWifiChip.h>
-#include <android/hardware/wifi/1.0/types.h>
-#include <android/hardware/wifi/1.2/types.h>
-#include <android/hardware/wifi/1.3/types.h>
-#include <android/hardware/wifi/1.4/IWifiChipEventCallback.h>
-#include <android/hardware/wifi/1.4/types.h>
-#include <android/hardware/wifi/1.5/IWifiChip.h>
-#include <android/hardware/wifi/1.5/types.h>
-
-#include "wifi_legacy_hal.h"
-
-/**
- * This file contains a bunch of functions to convert structs from the legacy
- * HAL to HIDL and vice versa.
- * TODO(b/32093047): Add unit tests for these conversion methods in the VTS test
- * suite.
- */
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_5 {
-namespace implementation {
-namespace hidl_struct_util {
-using namespace android::hardware::wifi::V1_0;
-
-// Chip conversion methods.
-bool convertLegacyFeaturesToHidlChipCapabilities(
-    uint64_t legacy_feature_set, uint32_t legacy_logger_feature_set,
-    uint32_t* hidl_caps);
-bool convertLegacyDebugRingBufferStatusToHidl(
-    const legacy_hal::wifi_ring_buffer_status& legacy_status,
-    WifiDebugRingBufferStatus* hidl_status);
-bool convertLegacyVectorOfDebugRingBufferStatusToHidl(
-    const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
-    std::vector<WifiDebugRingBufferStatus>* hidl_status_vec);
-bool convertLegacyWakeReasonStatsToHidl(
-    const legacy_hal::WakeReasonStats& legacy_stats,
-    WifiDebugHostWakeReasonStats* hidl_stats);
-legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
-    V1_1::IWifiChip::TxPowerScenario hidl_scenario);
-legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy(
-    V1_3::IWifiChip::LatencyMode hidl_latency_mode);
-legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2(
-    V1_2::IWifiChip::TxPowerScenario hidl_scenario);
-bool convertLegacyWifiMacInfosToHidl(
-    const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
-    std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>*
-        hidl_radio_mode_infos);
-legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(
-    IfaceType hidl_interface_type);
-legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy(
-    IWifiChip::MultiStaUseCase use_case);
-bool convertHidlCoexUnsafeChannelToLegacy(
-    const IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel,
-    legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel);
-bool convertHidlVectorOfCoexUnsafeChannelToLegacy(
-    const std::vector<IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels,
-    std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels);
-
-// STA iface conversion methods.
-bool convertLegacyFeaturesToHidlStaCapabilities(
-    uint64_t legacy_feature_set, uint32_t legacy_logger_feature_set,
-    uint32_t* hidl_caps);
-bool convertLegacyApfCapabilitiesToHidl(
-    const legacy_hal::PacketFilterCapabilities& legacy_caps,
-    StaApfPacketFilterCapabilities* hidl_caps);
-bool convertLegacyGscanCapabilitiesToHidl(
-    const legacy_hal::wifi_gscan_capabilities& legacy_caps,
-    StaBackgroundScanCapabilities* hidl_caps);
-legacy_hal::wifi_band convertHidlWifiBandToLegacy(V1_0::WifiBand band);
-bool convertHidlGscanParamsToLegacy(
-    const StaBackgroundScanParameters& hidl_scan_params,
-    legacy_hal::wifi_scan_cmd_params* legacy_scan_params);
-// |has_ie_data| indicates whether or not the wifi_scan_result includes 802.11
-// Information Elements (IEs)
-bool convertLegacyGscanResultToHidl(
-    const legacy_hal::wifi_scan_result& legacy_scan_result, bool has_ie_data,
-    StaScanResult* hidl_scan_result);
-// |cached_results| is assumed to not include IEs.
-bool convertLegacyVectorOfCachedGscanResultsToHidl(
-    const std::vector<legacy_hal::wifi_cached_scan_results>&
-        legacy_cached_scan_results,
-    std::vector<StaScanData>* hidl_scan_datas);
-bool convertLegacyLinkLayerStatsToHidl(
-    const legacy_hal::LinkLayerStats& legacy_stats,
-    StaLinkLayerStats* hidl_stats);
-bool convertLegacyRoamingCapabilitiesToHidl(
-    const legacy_hal::wifi_roaming_capabilities& legacy_caps,
-    StaRoamingCapabilities* hidl_caps);
-bool convertHidlRoamingConfigToLegacy(
-    const StaRoamingConfig& hidl_config,
-    legacy_hal::wifi_roaming_config* legacy_config);
-legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy(
-    StaRoamingState state);
-bool convertLegacyVectorOfDebugTxPacketFateToHidl(
-    const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
-    std::vector<WifiDebugTxPacketFateReport>* hidl_fates);
-bool convertLegacyVectorOfDebugRxPacketFateToHidl(
-    const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
-    std::vector<WifiDebugRxPacketFateReport>* hidl_fates);
-
-// NAN iface conversion methods.
-void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str,
-                            size_t max_len, WifiNanStatus* wifiNanStatus);
-bool convertHidlNanEnableRequestToLegacy(
-    const V1_4::NanEnableRequest& hidl_request,
-    legacy_hal::NanEnableRequest* legacy_request);
-bool convertHidlNanConfigRequestToLegacy(
-    const V1_4::NanConfigRequest& hidl_request,
-    legacy_hal::NanConfigRequest* legacy_request);
-bool convertHidlNanEnableRequest_1_4ToLegacy(
-    const V1_4::NanEnableRequest& hidl_request1,
-    const NanConfigRequestSupplemental& hidl_request2,
-    legacy_hal::NanEnableRequest* legacy_request);
-bool convertHidlNanConfigRequest_1_4ToLegacy(
-    const V1_4::NanConfigRequest& hidl_request1,
-    const NanConfigRequestSupplemental& hidl_request2,
-    legacy_hal::NanConfigRequest* legacy_request);
-bool convertHidlNanEnableRequest_1_5ToLegacy(
-    const V1_4::NanEnableRequest& hidl_request1,
-    const NanConfigRequestSupplemental& hidl_request2,
-    legacy_hal::NanEnableRequest* legacy_request);
-bool convertHidlNanConfigRequest_1_5ToLegacy(
-    const V1_4::NanConfigRequest& hidl_request1,
-    const NanConfigRequestSupplemental& hidl_request2,
-    legacy_hal::NanConfigRequest* legacy_request);
-bool convertHidlNanPublishRequestToLegacy(
-    const NanPublishRequest& hidl_request,
-    legacy_hal::NanPublishRequest* legacy_request);
-bool convertHidlNanSubscribeRequestToLegacy(
-    const NanSubscribeRequest& hidl_request,
-    legacy_hal::NanSubscribeRequest* legacy_request);
-bool convertHidlNanTransmitFollowupRequestToLegacy(
-    const NanTransmitFollowupRequest& hidl_request,
-    legacy_hal::NanTransmitFollowupRequest* legacy_request);
-bool convertHidlNanDataPathInitiatorRequestToLegacy(
-    const NanInitiateDataPathRequest& hidl_request,
-    legacy_hal::NanDataPathInitiatorRequest* legacy_request);
-bool convertHidlNanDataPathIndicationResponseToLegacy(
-    const NanRespondToDataPathIndicationRequest& hidl_response,
-    legacy_hal::NanDataPathIndicationResponse* legacy_response);
-bool convertLegacyNanResponseHeaderToHidl(
-    const legacy_hal::NanResponseMsg& legacy_response,
-    WifiNanStatus* wifiNanStatus);
-bool convertLegacyNanCapabilitiesResponseToHidl(
-    const legacy_hal::NanCapabilities& legacy_response,
-    NanCapabilities* hidl_response);
-bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind,
-                                    NanMatchInd* hidl_ind);
-bool convertLegacyNanFollowupIndToHidl(
-    const legacy_hal::NanFollowupInd& legacy_ind,
-    NanFollowupReceivedInd* hidl_ind);
-bool convertLegacyNanDataPathRequestIndToHidl(
-    const legacy_hal::NanDataPathRequestInd& legacy_ind,
-    NanDataPathRequestInd* hidl_ind);
-bool convertLegacyNanDataPathConfirmIndToHidl(
-    const legacy_hal::NanDataPathConfirmInd& legacy_ind,
-    V1_2::NanDataPathConfirmInd* hidl_ind);
-bool convertLegacyNanDataPathScheduleUpdateIndToHidl(
-    const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
-    V1_2::NanDataPathScheduleUpdateInd* hidl_ind);
-
-// RTT controller conversion methods.
-bool convertHidlVectorOfRttConfigToLegacy(
-    const std::vector<V1_4::RttConfig>& hidl_configs,
-    std::vector<legacy_hal::wifi_rtt_config>* legacy_configs);
-bool convertHidlRttLciInformationToLegacy(
-    const RttLciInformation& hidl_info,
-    legacy_hal::wifi_lci_information* legacy_info);
-bool convertHidlRttLcrInformationToLegacy(
-    const RttLcrInformation& hidl_info,
-    legacy_hal::wifi_lcr_information* legacy_info);
-bool convertHidlRttResponderToLegacy(
-    const V1_4::RttResponder& hidl_responder,
-    legacy_hal::wifi_rtt_responder* legacy_responder);
-bool convertHidlWifiChannelInfoToLegacy(
-    const WifiChannelInfo& hidl_info,
-    legacy_hal::wifi_channel_info* legacy_info);
-bool convertLegacyRttResponderToHidl(
-    const legacy_hal::wifi_rtt_responder& legacy_responder,
-    V1_4::RttResponder* hidl_responder);
-bool convertLegacyRttCapabilitiesToHidl(
-    const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
-    V1_4::RttCapabilities* hidl_capabilities);
-bool convertLegacyVectorOfRttResultToHidl(
-    const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
-    std::vector<V1_4::RttResult>* hidl_results);
-uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand band);
-uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask);
-uint32_t convertHidlUsableChannelFilterToLegacy(uint32_t hidl_filter_mask);
-bool convertLegacyWifiUsableChannelsToHidl(
-    const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels,
-    std::vector<V1_5::WifiUsableChannel>* hidl_usable_channels);
-bool convertLegacyPeerInfoStatsToHidl(
-    const legacy_hal::WifiPeerInfo& legacy_peer_info_stats,
-    StaPeerInfo* hidl_peer_info_stats);
-bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate,
-                                     V1_4::WifiRateInfo* hidl_rate);
-}  // namespace hidl_struct_util
-}  // namespace implementation
-}  // namespace V1_5
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // HIDL_STRUCT_UTIL_H_
diff --git a/wifi/1.5/default/tests/mock_wifi_legacy_hal.h b/wifi/1.5/default/tests/mock_wifi_legacy_hal.h
deleted file mode 100644
index 826b35f..0000000
--- a/wifi/1.5/default/tests/mock_wifi_legacy_hal.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MOCK_WIFI_LEGACY_HAL_H_
-#define MOCK_WIFI_LEGACY_HAL_H_
-
-#include <gmock/gmock.h>
-
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_5 {
-namespace implementation {
-namespace legacy_hal {
-
-class MockWifiLegacyHal : public WifiLegacyHal {
-   public:
-    MockWifiLegacyHal(
-        const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
-        const wifi_hal_fn& fn, bool is_primary);
-    MOCK_METHOD0(initialize, wifi_error());
-    MOCK_METHOD0(start, wifi_error());
-    MOCK_METHOD2(stop, wifi_error(std::unique_lock<std::recursive_mutex>*,
-                                  const std::function<void()>&));
-    MOCK_METHOD2(setDfsFlag, wifi_error(const std::string&, bool));
-    MOCK_METHOD2(registerRadioModeChangeCallbackHandler,
-                 wifi_error(const std::string&,
-                            const on_radio_mode_change_callback&));
-    MOCK_METHOD1(getFirmwareVersion, std::pair<wifi_error, std::string>(
-                                         const std::string& iface_name));
-    MOCK_METHOD1(getDriverVersion, std::pair<wifi_error, std::string>(
-                                       const std::string& iface_name));
-
-    MOCK_METHOD2(selectTxPowerScenario,
-                 wifi_error(const std::string& iface_name,
-                            wifi_power_scenario scenario));
-    MOCK_METHOD1(resetTxPowerScenario,
-                 wifi_error(const std::string& iface_name));
-    MOCK_METHOD2(nanRegisterCallbackHandlers,
-                 wifi_error(const std::string&, const NanCallbackHandlers&));
-    MOCK_METHOD2(nanDisableRequest,
-                 wifi_error(const std::string&, transaction_id));
-    MOCK_METHOD3(nanDataInterfaceDelete,
-                 wifi_error(const std::string&, transaction_id,
-                            const std::string&));
-    MOCK_METHOD2(createVirtualInterface,
-                 wifi_error(const std::string& ifname,
-                            wifi_interface_type iftype));
-    MOCK_METHOD1(deleteVirtualInterface, wifi_error(const std::string& ifname));
-    MOCK_METHOD0(waitForDriverReady, wifi_error());
-};
-}  // namespace legacy_hal
-}  // namespace implementation
-}  // namespace V1_5
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // MOCK_WIFI_LEGACY_HAL_H_
diff --git a/wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp
deleted file mode 100644
index 32da55e..0000000
--- a/wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <cutils/properties.h>
-#include <gmock/gmock.h>
-
-#undef NAN  // This is weird, NAN is defined in bionic/libc/include/math.h:38
-#include "wifi_nan_iface.h"
-
-#include "mock_interface_tool.h"
-#include "mock_wifi_feature_flags.h"
-#include "mock_wifi_iface_util.h"
-#include "mock_wifi_legacy_hal.h"
-
-using testing::NiceMock;
-using testing::Return;
-using testing::Test;
-
-namespace {
-constexpr char kIfaceName[] = "mockWlan0";
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_5 {
-namespace implementation {
-
-using android::hardware::wifi::V1_2::NanDataPathConfirmInd;
-
-bool CaptureIfaceEventHandlers(
-    const std::string& /* iface_name*/,
-    iface_util::IfaceEventHandlers in_iface_event_handlers,
-    iface_util::IfaceEventHandlers* out_iface_event_handlers) {
-    *out_iface_event_handlers = in_iface_event_handlers;
-    return true;
-}
-
-class MockNanIfaceEventCallback : public IWifiNanIfaceEventCallback {
-   public:
-    MockNanIfaceEventCallback() = default;
-
-    MOCK_METHOD3(
-        notifyCapabilitiesResponse,
-        Return<void>(uint16_t, const WifiNanStatus&,
-                     const android::hardware::wifi::V1_0::NanCapabilities&));
-    MOCK_METHOD2(notifyEnableResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&));
-    MOCK_METHOD2(notifyConfigResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&));
-    MOCK_METHOD2(notifyDisableResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&));
-    MOCK_METHOD3(notifyStartPublishResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&, uint8_t));
-    MOCK_METHOD2(notifyStopPublishResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&));
-    MOCK_METHOD3(notifyStartSubscribeResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&, uint8_t));
-    MOCK_METHOD2(notifyStopSubscribeResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&));
-    MOCK_METHOD2(notifyTransmitFollowupResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&));
-    MOCK_METHOD2(notifyCreateDataInterfaceResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&));
-    MOCK_METHOD2(notifyDeleteDataInterfaceResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&));
-    MOCK_METHOD3(notifyInitiateDataPathResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&, uint32_t));
-    MOCK_METHOD2(notifyRespondToDataPathIndicationResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&));
-    MOCK_METHOD2(notifyTerminateDataPathResponse,
-                 Return<void>(uint16_t, const WifiNanStatus&));
-    MOCK_METHOD1(eventClusterEvent, Return<void>(const NanClusterEventInd&));
-    MOCK_METHOD1(eventDisabled, Return<void>(const WifiNanStatus&));
-    MOCK_METHOD2(eventPublishTerminated,
-                 Return<void>(uint8_t, const WifiNanStatus&));
-    MOCK_METHOD2(eventSubscribeTerminated,
-                 Return<void>(uint8_t, const WifiNanStatus&));
-    MOCK_METHOD1(eventMatch, Return<void>(const NanMatchInd&));
-    MOCK_METHOD2(eventMatchExpired, Return<void>(uint8_t, uint32_t));
-    MOCK_METHOD1(eventFollowupReceived,
-                 Return<void>(const NanFollowupReceivedInd&));
-    MOCK_METHOD2(eventTransmitFollowup,
-                 Return<void>(uint16_t, const WifiNanStatus&));
-    MOCK_METHOD1(eventDataPathRequest,
-                 Return<void>(const NanDataPathRequestInd&));
-    MOCK_METHOD1(
-        eventDataPathConfirm,
-        Return<void>(
-            const android::hardware::wifi::V1_0::NanDataPathConfirmInd&));
-    MOCK_METHOD1(eventDataPathTerminated, Return<void>(uint32_t));
-    MOCK_METHOD1(eventDataPathConfirm_1_2,
-                 Return<void>(const NanDataPathConfirmInd&));
-    MOCK_METHOD1(eventDataPathScheduleUpdate,
-                 Return<void>(const NanDataPathScheduleUpdateInd&));
-    MOCK_METHOD3(notifyCapabilitiesResponse_1_5,
-                 Return<void>(uint16_t, const WifiNanStatus&,
-                              const NanCapabilities&));
-};
-
-class WifiNanIfaceTest : public Test {
-   protected:
-    legacy_hal::wifi_hal_fn fake_func_table_;
-    std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
-        new NiceMock<wifi_system::MockInterfaceTool>};
-    std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
-        new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_,
-                                                    fake_func_table_, true)};
-    std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
-        new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_, legacy_hal_)};
-};
-
-TEST_F(WifiNanIfaceTest, IfacEventHandlers_OnStateToggleOffOn) {
-    iface_util::IfaceEventHandlers captured_iface_event_handlers = {};
-    EXPECT_CALL(*legacy_hal_,
-                nanRegisterCallbackHandlers(testing::_, testing::_))
-        .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
-    EXPECT_CALL(*iface_util_,
-                registerIfaceEventHandlers(testing::_, testing::_))
-        .WillOnce(testing::Invoke(
-            bind(CaptureIfaceEventHandlers, std::placeholders::_1,
-                 std::placeholders::_2, &captured_iface_event_handlers)));
-    sp<WifiNanIface> nan_iface =
-        new WifiNanIface(kIfaceName, false, legacy_hal_, iface_util_);
-
-    // Register a mock nan event callback.
-    sp<NiceMock<MockNanIfaceEventCallback>> mock_event_callback{
-        new NiceMock<MockNanIfaceEventCallback>};
-    nan_iface->registerEventCallback(
-        mock_event_callback, [](const WifiStatus& status) {
-            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-        });
-    // Ensure that the eventDisabled() function in mock callback will be
-    // invoked.
-    WifiNanStatus expected_nan_status = {
-        NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
-    EXPECT_CALL(*mock_event_callback, eventDisabled(expected_nan_status))
-        .Times(1);
-
-    // Trigger the iface state toggle callback.
-    captured_iface_event_handlers.on_state_toggle_off_on(kIfaceName);
-}
-}  // namespace implementation
-}  // namespace V1_5
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h
deleted file mode 100644
index bd40ead..0000000
--- a/wifi/1.5/default/wifi_chip.h
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_CHIP_H_
-#define WIFI_CHIP_H_
-
-#include <list>
-#include <map>
-#include <mutex>
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.4/IWifiRttController.h>
-#include <android/hardware/wifi/1.5/IWifiChip.h>
-
-#include "hidl_callback_util.h"
-#include "ringbuffer.h"
-#include "wifi_ap_iface.h"
-#include "wifi_feature_flags.h"
-#include "wifi_legacy_hal.h"
-#include "wifi_mode_controller.h"
-#include "wifi_nan_iface.h"
-#include "wifi_p2p_iface.h"
-#include "wifi_rtt_controller.h"
-#include "wifi_sta_iface.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_5 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * HIDL interface object used to control a Wifi HAL chip instance.
- * Since there is only a single chip instance used today, there is no
- * identifying handle information stored here.
- */
-class WifiChip : public V1_5::IWifiChip {
-   public:
-    WifiChip(ChipId chip_id, bool is_primary,
-             const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
-             const std::weak_ptr<mode_controller::WifiModeController>
-                 mode_controller,
-             const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
-             const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
-             const std::function<void(const std::string&)>&
-                 subsystemCallbackHandler);
-    // HIDL does not provide a built-in mechanism to let the server invalidate
-    // a HIDL interface object after creation. If any client process holds onto
-    // a reference to the object in their context, any method calls on that
-    // reference will continue to be directed to the server.
-    //
-    // However Wifi HAL needs to control the lifetime of these objects. So, add
-    // a public |invalidate| method to |WifiChip| and it's child objects. This
-    // will be used to mark an object invalid when either:
-    // a) Wifi HAL is stopped, or
-    // b) Wifi Chip is reconfigured.
-    //
-    // All HIDL method implementations should check if the object is still
-    // marked valid before processing them.
-    void invalidate();
-    bool isValid();
-    std::set<sp<V1_4::IWifiChipEventCallback>> getEventCallbacks();
-
-    // HIDL methods exposed.
-    Return<void> getId(getId_cb hidl_status_cb) override;
-    // Deprecated support for this callback
-    Return<void> registerEventCallback(
-        const sp<V1_0::IWifiChipEventCallback>& event_callback,
-        registerEventCallback_cb hidl_status_cb) override;
-    Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
-    Return<void> getAvailableModes(
-        getAvailableModes_cb hidl_status_cb) override;
-    Return<void> configureChip(ChipModeId mode_id,
-                               configureChip_cb hidl_status_cb) override;
-    Return<void> getMode(getMode_cb hidl_status_cb) override;
-    Return<void> requestChipDebugInfo(
-        requestChipDebugInfo_cb hidl_status_cb) override;
-    Return<void> requestDriverDebugDump(
-        requestDriverDebugDump_cb hidl_status_cb) override;
-    Return<void> requestFirmwareDebugDump(
-        requestFirmwareDebugDump_cb hidl_status_cb) override;
-    Return<void> createApIface(createApIface_cb hidl_status_cb) override;
-    Return<void> createBridgedApIface(
-        createBridgedApIface_cb hidl_status_cb) override;
-    Return<void> getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override;
-    Return<void> getApIface(const hidl_string& ifname,
-                            getApIface_cb hidl_status_cb) override;
-    Return<void> removeApIface(const hidl_string& ifname,
-                               removeApIface_cb hidl_status_cb) override;
-    Return<void> removeIfaceInstanceFromBridgedApIface(
-        const hidl_string& brIfaceName, const hidl_string& ifaceInstanceName,
-        removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) override;
-    Return<void> createNanIface(createNanIface_cb hidl_status_cb) override;
-    Return<void> getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override;
-    Return<void> getNanIface(const hidl_string& ifname,
-                             getNanIface_cb hidl_status_cb) override;
-    Return<void> removeNanIface(const hidl_string& ifname,
-                                removeNanIface_cb hidl_status_cb) override;
-    Return<void> createP2pIface(createP2pIface_cb hidl_status_cb) override;
-    Return<void> getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) override;
-    Return<void> getP2pIface(const hidl_string& ifname,
-                             getP2pIface_cb hidl_status_cb) override;
-    Return<void> removeP2pIface(const hidl_string& ifname,
-                                removeP2pIface_cb hidl_status_cb) override;
-    Return<void> createStaIface(createStaIface_cb hidl_status_cb) override;
-    Return<void> getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) override;
-    Return<void> getStaIface(const hidl_string& ifname,
-                             getStaIface_cb hidl_status_cb) override;
-    Return<void> removeStaIface(const hidl_string& ifname,
-                                removeStaIface_cb hidl_status_cb) override;
-    Return<void> createRttController(
-        const sp<IWifiIface>& bound_iface,
-        createRttController_cb hidl_status_cb) override;
-    Return<void> getDebugRingBuffersStatus(
-        getDebugRingBuffersStatus_cb hidl_status_cb) override;
-    Return<void> startLoggingToDebugRingBuffer(
-        const hidl_string& ring_name,
-        WifiDebugRingBufferVerboseLevel verbose_level,
-        uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes,
-        startLoggingToDebugRingBuffer_cb hidl_status_cb) override;
-    Return<void> forceDumpToDebugRingBuffer(
-        const hidl_string& ring_name,
-        forceDumpToDebugRingBuffer_cb hidl_status_cb) override;
-    Return<void> flushRingBufferToFile(
-        flushRingBufferToFile_cb hidl_status_cb) override;
-    Return<void> stopLoggingToDebugRingBuffer(
-        stopLoggingToDebugRingBuffer_cb hidl_status_cb) override;
-    Return<void> getDebugHostWakeReasonStats(
-        getDebugHostWakeReasonStats_cb hidl_status_cb) override;
-    Return<void> enableDebugErrorAlerts(
-        bool enable, enableDebugErrorAlerts_cb hidl_status_cb) override;
-    Return<void> selectTxPowerScenario(
-        V1_1::IWifiChip::TxPowerScenario scenario,
-        selectTxPowerScenario_cb hidl_status_cb) override;
-    Return<void> resetTxPowerScenario(
-        resetTxPowerScenario_cb hidl_status_cb) override;
-    Return<void> setLatencyMode(LatencyMode mode,
-                                setLatencyMode_cb hidl_status_cb) override;
-    Return<void> registerEventCallback_1_2(
-        const sp<V1_2::IWifiChipEventCallback>& event_callback,
-        registerEventCallback_1_2_cb hidl_status_cb) override;
-    Return<void> selectTxPowerScenario_1_2(
-        TxPowerScenario scenario,
-        selectTxPowerScenario_cb hidl_status_cb) override;
-    Return<void> getCapabilities_1_3(
-        getCapabilities_cb hidl_status_cb) override;
-    Return<void> getCapabilities_1_5(
-        getCapabilities_1_5_cb hidl_status_cb) override;
-    Return<void> debug(const hidl_handle& handle,
-                       const hidl_vec<hidl_string>& options) override;
-    Return<void> createRttController_1_4(
-        const sp<IWifiIface>& bound_iface,
-        createRttController_1_4_cb hidl_status_cb) override;
-    Return<void> registerEventCallback_1_4(
-        const sp<V1_4::IWifiChipEventCallback>& event_callback,
-        registerEventCallback_1_4_cb hidl_status_cb) override;
-    Return<void> setMultiStaPrimaryConnection(
-        const hidl_string& ifname,
-        setMultiStaPrimaryConnection_cb hidl_status_cb) override;
-    Return<void> setMultiStaUseCase(
-        MultiStaUseCase use_case,
-        setMultiStaUseCase_cb hidl_status_cb) override;
-    Return<void> setCoexUnsafeChannels(
-        const hidl_vec<CoexUnsafeChannel>& unsafe_channels,
-        hidl_bitfield<IfaceType> restrictions,
-        setCoexUnsafeChannels_cb hidl_status_cb) override;
-    Return<void> setCountryCode(const hidl_array<int8_t, 2>& code,
-                                setCountryCode_cb _hidl_cb) override;
-    Return<void> getUsableChannels(
-        WifiBand band, hidl_bitfield<WifiIfaceMode> ifaceModeMask,
-        hidl_bitfield<UsableChannelFilter> filterMask,
-        getUsableChannels_cb _hidl_cb) override;
-    Return<void> triggerSubsystemRestart(
-        triggerSubsystemRestart_cb hidl_status_cb) override;
-
-   private:
-    void invalidateAndRemoveAllIfaces();
-    // When a STA iface is removed any dependent NAN-ifaces/RTT-controllers are
-    // invalidated & removed.
-    void invalidateAndRemoveDependencies(const std::string& removed_iface_name);
-
-    // Corresponding worker functions for the HIDL methods.
-    std::pair<WifiStatus, ChipId> getIdInternal();
-    // Deprecated support for this callback
-    WifiStatus registerEventCallbackInternal(
-        const sp<V1_0::IWifiChipEventCallback>& event_callback);
-    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
-    std::pair<WifiStatus, std::vector<ChipMode>> getAvailableModesInternal();
-    WifiStatus configureChipInternal(
-        std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
-    std::pair<WifiStatus, uint32_t> getModeInternal();
-    std::pair<WifiStatus, IWifiChip::ChipDebugInfo>
-    requestChipDebugInfoInternal();
-    std::pair<WifiStatus, std::vector<uint8_t>>
-    requestDriverDebugDumpInternal();
-    std::pair<WifiStatus, std::vector<uint8_t>>
-    requestFirmwareDebugDumpInternal();
-    sp<WifiApIface> newWifiApIface(std::string& ifname);
-    WifiStatus createVirtualApInterface(const std::string& apVirtIf);
-    std::pair<WifiStatus, sp<V1_5::IWifiApIface>> createApIfaceInternal();
-    std::pair<WifiStatus, sp<V1_5::IWifiApIface>>
-    createBridgedApIfaceInternal();
-    std::pair<WifiStatus, std::vector<hidl_string>> getApIfaceNamesInternal();
-    std::pair<WifiStatus, sp<V1_5::IWifiApIface>> getApIfaceInternal(
-        const std::string& ifname);
-    WifiStatus removeApIfaceInternal(const std::string& ifname);
-    WifiStatus removeIfaceInstanceFromBridgedApIfaceInternal(
-        const std::string& brIfaceName, const std::string& ifInstanceName);
-    std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> createNanIfaceInternal();
-    std::pair<WifiStatus, std::vector<hidl_string>> getNanIfaceNamesInternal();
-    std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> getNanIfaceInternal(
-        const std::string& ifname);
-    WifiStatus removeNanIfaceInternal(const std::string& ifname);
-    std::pair<WifiStatus, sp<IWifiP2pIface>> createP2pIfaceInternal();
-    std::pair<WifiStatus, std::vector<hidl_string>> getP2pIfaceNamesInternal();
-    std::pair<WifiStatus, sp<IWifiP2pIface>> getP2pIfaceInternal(
-        const std::string& ifname);
-    WifiStatus removeP2pIfaceInternal(const std::string& ifname);
-    std::pair<WifiStatus, sp<V1_5::IWifiStaIface>> createStaIfaceInternal();
-    std::pair<WifiStatus, std::vector<hidl_string>> getStaIfaceNamesInternal();
-    std::pair<WifiStatus, sp<V1_5::IWifiStaIface>> getStaIfaceInternal(
-        const std::string& ifname);
-    WifiStatus removeStaIfaceInternal(const std::string& ifname);
-    std::pair<WifiStatus, sp<V1_0::IWifiRttController>>
-    createRttControllerInternal(const sp<IWifiIface>& bound_iface);
-    std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
-    getDebugRingBuffersStatusInternal();
-    WifiStatus startLoggingToDebugRingBufferInternal(
-        const hidl_string& ring_name,
-        WifiDebugRingBufferVerboseLevel verbose_level,
-        uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes);
-    WifiStatus forceDumpToDebugRingBufferInternal(const hidl_string& ring_name);
-    WifiStatus flushRingBufferToFileInternal();
-    WifiStatus stopLoggingToDebugRingBufferInternal();
-    std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
-    getDebugHostWakeReasonStatsInternal();
-    WifiStatus enableDebugErrorAlertsInternal(bool enable);
-    WifiStatus selectTxPowerScenarioInternal(
-        V1_1::IWifiChip::TxPowerScenario scenario);
-    WifiStatus resetTxPowerScenarioInternal();
-    WifiStatus setLatencyModeInternal(LatencyMode mode);
-    WifiStatus registerEventCallbackInternal_1_2(
-        const sp<V1_2::IWifiChipEventCallback>& event_callback);
-    WifiStatus selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario);
-    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_3();
-    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_5();
-    std::pair<WifiStatus, sp<V1_4::IWifiRttController>>
-    createRttControllerInternal_1_4(const sp<IWifiIface>& bound_iface);
-    WifiStatus registerEventCallbackInternal_1_4(
-        const sp<V1_4::IWifiChipEventCallback>& event_callback);
-    WifiStatus setMultiStaPrimaryConnectionInternal(const std::string& ifname);
-    WifiStatus setMultiStaUseCaseInternal(MultiStaUseCase use_case);
-    WifiStatus setCoexUnsafeChannelsInternal(
-        std::vector<CoexUnsafeChannel> unsafe_channels, uint32_t restrictions);
-    WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code);
-    std::pair<WifiStatus, std::vector<WifiUsableChannel>>
-    getUsableChannelsInternal(WifiBand band, uint32_t ifaceModeMask,
-                              uint32_t filterMask);
-    WifiStatus handleChipConfiguration(
-        std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
-    WifiStatus registerDebugRingBufferCallback();
-    WifiStatus registerRadioModeChangeCallback();
-
-    std::vector<V1_4::IWifiChip::ChipIfaceCombination>
-    getCurrentModeIfaceCombinations();
-    std::map<IfaceType, size_t> getCurrentIfaceCombination();
-    std::vector<std::map<IfaceType, size_t>> expandIfaceCombinations(
-        const V1_4::IWifiChip::ChipIfaceCombination& combination);
-    bool canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(
-        const std::map<IfaceType, size_t>& expanded_combo,
-        IfaceType requested_type);
-    bool canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(
-        IfaceType requested_type);
-    bool canExpandedIfaceComboSupportIfaceCombo(
-        const std::map<IfaceType, size_t>& expanded_combo,
-        const std::map<IfaceType, size_t>& req_combo);
-    bool canCurrentModeSupportIfaceCombo(
-        const std::map<IfaceType, size_t>& req_combo);
-    bool canCurrentModeSupportIfaceOfType(IfaceType requested_type);
-    bool isValidModeId(ChipModeId mode_id);
-    bool isStaApConcurrencyAllowedInCurrentMode();
-    bool isDualStaConcurrencyAllowedInCurrentMode();
-    uint32_t startIdxOfApIface();
-    std::string getFirstActiveWlanIfaceName();
-    std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx);
-    std::string allocateApIfaceName();
-    std::vector<std::string> allocateBridgedApInstanceNames();
-    std::string allocateStaIfaceName();
-    bool writeRingbufferFilesInternal();
-    std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx);
-    void invalidateAndClearBridgedApAll();
-    void invalidateAndClearBridgedAp(const std::string& br_name);
-    bool findUsingNameFromBridgedApInstances(const std::string& name);
-    WifiStatus triggerSubsystemRestartInternal();
-
-    ChipId chip_id_;
-    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-    std::weak_ptr<mode_controller::WifiModeController> mode_controller_;
-    std::shared_ptr<iface_util::WifiIfaceUtil> iface_util_;
-    std::vector<sp<WifiApIface>> ap_ifaces_;
-    std::vector<sp<WifiNanIface>> nan_ifaces_;
-    std::vector<sp<WifiP2pIface>> p2p_ifaces_;
-    std::vector<sp<WifiStaIface>> sta_ifaces_;
-    std::vector<sp<WifiRttController>> rtt_controllers_;
-    std::map<std::string, Ringbuffer> ringbuffer_map_;
-    bool is_valid_;
-    // Members pertaining to chip configuration.
-    uint32_t current_mode_id_;
-    std::mutex lock_t;
-    std::vector<V1_4::IWifiChip::ChipMode> modes_;
-    // The legacy ring buffer callback API has only a global callback
-    // registration mechanism. Use this to check if we have already
-    // registered a callback.
-    bool debug_ring_buffer_cb_registered_;
-    hidl_callback_util::HidlCallbackHandler<V1_4::IWifiChipEventCallback>
-        event_cb_handler_;
-
-    const std::function<void(const std::string&)> subsystemCallbackHandler_;
-    std::map<std::string, std::vector<std::string>> br_ifaces_ap_instances_;
-    DISALLOW_COPY_AND_ASSIGN(WifiChip);
-};
-
-}  // namespace implementation
-}  // namespace V1_5
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_CHIP_H_
diff --git a/wifi/1.5/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
deleted file mode 100644
index 5074252..0000000
--- a/wifi/1.5/default/wifi_legacy_hal.cpp
+++ /dev/null
@@ -1,1725 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <array>
-#include <chrono>
-
-#include <android-base/logging.h>
-#include <cutils/properties.h>
-#include <net/if.h>
-
-#include "hidl_sync_util.h"
-#include "wifi_legacy_hal.h"
-#include "wifi_legacy_hal_stubs.h"
-
-namespace {
-// Constants ported over from the legacy HAL calling code
-// (com_android_server_wifi_WifiNative.cpp). This will all be thrown
-// away when this shim layer is replaced by the real vendor
-// implementation.
-static constexpr uint32_t kMaxVersionStringLength = 256;
-static constexpr uint32_t kMaxCachedGscanResults = 64;
-static constexpr uint32_t kMaxGscanFrequenciesForBand = 64;
-static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
-static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
-static constexpr uint32_t kMaxRingBuffers = 10;
-static constexpr uint32_t kMaxWifiUsableChannels = 256;
-// need a long timeout (1000ms) for chips that unload their driver.
-static constexpr uint32_t kMaxStopCompleteWaitMs = 1000;
-static constexpr char kDriverPropName[] = "wlan.driver.status";
-
-// Helper function to create a non-const char* for legacy Hal API's.
-std::vector<char> makeCharVec(const std::string& str) {
-    std::vector<char> vec(str.size() + 1);
-    vec.assign(str.begin(), str.end());
-    vec.push_back('\0');
-    return vec;
-}
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_5 {
-namespace implementation {
-namespace legacy_hal {
-
-// Legacy HAL functions accept "C" style function pointers, so use global
-// functions to pass to the legacy HAL function and store the corresponding
-// std::function methods to be invoked.
-//
-// Callback to be invoked once |stop| is complete
-std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
-void onAsyncStopComplete(wifi_handle handle) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_stop_complete_internal_callback) {
-        on_stop_complete_internal_callback(handle);
-        // Invalidate this callback since we don't want this firing again.
-        on_stop_complete_internal_callback = nullptr;
-    }
-}
-
-// Callback to be invoked for driver dump.
-std::function<void(char*, int)> on_driver_memory_dump_internal_callback;
-void onSyncDriverMemoryDump(char* buffer, int buffer_size) {
-    if (on_driver_memory_dump_internal_callback) {
-        on_driver_memory_dump_internal_callback(buffer, buffer_size);
-    }
-}
-
-// Callback to be invoked for firmware dump.
-std::function<void(char*, int)> on_firmware_memory_dump_internal_callback;
-void onSyncFirmwareMemoryDump(char* buffer, int buffer_size) {
-    if (on_firmware_memory_dump_internal_callback) {
-        on_firmware_memory_dump_internal_callback(buffer, buffer_size);
-    }
-}
-
-// Callback to be invoked for Gscan events.
-std::function<void(wifi_request_id, wifi_scan_event)>
-    on_gscan_event_internal_callback;
-void onAsyncGscanEvent(wifi_request_id id, wifi_scan_event event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_gscan_event_internal_callback) {
-        on_gscan_event_internal_callback(id, event);
-    }
-}
-
-// Callback to be invoked for Gscan full results.
-std::function<void(wifi_request_id, wifi_scan_result*, uint32_t)>
-    on_gscan_full_result_internal_callback;
-void onAsyncGscanFullResult(wifi_request_id id, wifi_scan_result* result,
-                            uint32_t buckets_scanned) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_gscan_full_result_internal_callback) {
-        on_gscan_full_result_internal_callback(id, result, buckets_scanned);
-    }
-}
-
-// Callback to be invoked for link layer stats results.
-std::function<void((wifi_request_id, wifi_iface_stat*, int, wifi_radio_stat*))>
-    on_link_layer_stats_result_internal_callback;
-void onSyncLinkLayerStatsResult(wifi_request_id id, wifi_iface_stat* iface_stat,
-                                int num_radios, wifi_radio_stat* radio_stat) {
-    if (on_link_layer_stats_result_internal_callback) {
-        on_link_layer_stats_result_internal_callback(id, iface_stat, num_radios,
-                                                     radio_stat);
-    }
-}
-
-// Callback to be invoked for rssi threshold breach.
-std::function<void((wifi_request_id, uint8_t*, int8_t))>
-    on_rssi_threshold_breached_internal_callback;
-void onAsyncRssiThresholdBreached(wifi_request_id id, uint8_t* bssid,
-                                  int8_t rssi) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_rssi_threshold_breached_internal_callback) {
-        on_rssi_threshold_breached_internal_callback(id, bssid, rssi);
-    }
-}
-
-// Callback to be invoked for ring buffer data indication.
-std::function<void(char*, char*, int, wifi_ring_buffer_status*)>
-    on_ring_buffer_data_internal_callback;
-void onAsyncRingBufferData(char* ring_name, char* buffer, int buffer_size,
-                           wifi_ring_buffer_status* status) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_ring_buffer_data_internal_callback) {
-        on_ring_buffer_data_internal_callback(ring_name, buffer, buffer_size,
-                                              status);
-    }
-}
-
-// Callback to be invoked for error alert indication.
-std::function<void(wifi_request_id, char*, int, int)>
-    on_error_alert_internal_callback;
-void onAsyncErrorAlert(wifi_request_id id, char* buffer, int buffer_size,
-                       int err_code) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_error_alert_internal_callback) {
-        on_error_alert_internal_callback(id, buffer, buffer_size, err_code);
-    }
-}
-
-// Callback to be invoked for radio mode change indication.
-std::function<void(wifi_request_id, uint32_t, wifi_mac_info*)>
-    on_radio_mode_change_internal_callback;
-void onAsyncRadioModeChange(wifi_request_id id, uint32_t num_macs,
-                            wifi_mac_info* mac_infos) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_radio_mode_change_internal_callback) {
-        on_radio_mode_change_internal_callback(id, num_macs, mac_infos);
-    }
-}
-
-// Callback to be invoked to report subsystem restart
-std::function<void(const char*)> on_subsystem_restart_internal_callback;
-void onAsyncSubsystemRestart(const char* error) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_subsystem_restart_internal_callback) {
-        on_subsystem_restart_internal_callback(error);
-    }
-}
-
-// Callback to be invoked for rtt results results.
-std::function<void(wifi_request_id, unsigned num_results,
-                   wifi_rtt_result* rtt_results[])>
-    on_rtt_results_internal_callback;
-void onAsyncRttResults(wifi_request_id id, unsigned num_results,
-                       wifi_rtt_result* rtt_results[]) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_rtt_results_internal_callback) {
-        on_rtt_results_internal_callback(id, num_results, rtt_results);
-        on_rtt_results_internal_callback = nullptr;
-    }
-}
-
-// Callbacks for the various NAN operations.
-// NOTE: These have very little conversions to perform before invoking the user
-// callbacks.
-// So, handle all of them here directly to avoid adding an unnecessary layer.
-std::function<void(transaction_id, const NanResponseMsg&)>
-    on_nan_notify_response_user_callback;
-void onAysncNanNotifyResponse(transaction_id id, NanResponseMsg* msg) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_notify_response_user_callback && msg) {
-        on_nan_notify_response_user_callback(id, *msg);
-    }
-}
-
-std::function<void(const NanPublishRepliedInd&)>
-    on_nan_event_publish_replied_user_callback;
-void onAysncNanEventPublishReplied(NanPublishRepliedInd* /* event */) {
-    LOG(ERROR) << "onAysncNanEventPublishReplied triggered";
-}
-
-std::function<void(const NanPublishTerminatedInd&)>
-    on_nan_event_publish_terminated_user_callback;
-void onAysncNanEventPublishTerminated(NanPublishTerminatedInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_publish_terminated_user_callback && event) {
-        on_nan_event_publish_terminated_user_callback(*event);
-    }
-}
-
-std::function<void(const NanMatchInd&)> on_nan_event_match_user_callback;
-void onAysncNanEventMatch(NanMatchInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_match_user_callback && event) {
-        on_nan_event_match_user_callback(*event);
-    }
-}
-
-std::function<void(const NanMatchExpiredInd&)>
-    on_nan_event_match_expired_user_callback;
-void onAysncNanEventMatchExpired(NanMatchExpiredInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_match_expired_user_callback && event) {
-        on_nan_event_match_expired_user_callback(*event);
-    }
-}
-
-std::function<void(const NanSubscribeTerminatedInd&)>
-    on_nan_event_subscribe_terminated_user_callback;
-void onAysncNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_subscribe_terminated_user_callback && event) {
-        on_nan_event_subscribe_terminated_user_callback(*event);
-    }
-}
-
-std::function<void(const NanFollowupInd&)> on_nan_event_followup_user_callback;
-void onAysncNanEventFollowup(NanFollowupInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_followup_user_callback && event) {
-        on_nan_event_followup_user_callback(*event);
-    }
-}
-
-std::function<void(const NanDiscEngEventInd&)>
-    on_nan_event_disc_eng_event_user_callback;
-void onAysncNanEventDiscEngEvent(NanDiscEngEventInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_disc_eng_event_user_callback && event) {
-        on_nan_event_disc_eng_event_user_callback(*event);
-    }
-}
-
-std::function<void(const NanDisabledInd&)> on_nan_event_disabled_user_callback;
-void onAysncNanEventDisabled(NanDisabledInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_disabled_user_callback && event) {
-        on_nan_event_disabled_user_callback(*event);
-    }
-}
-
-std::function<void(const NanTCAInd&)> on_nan_event_tca_user_callback;
-void onAysncNanEventTca(NanTCAInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_tca_user_callback && event) {
-        on_nan_event_tca_user_callback(*event);
-    }
-}
-
-std::function<void(const NanBeaconSdfPayloadInd&)>
-    on_nan_event_beacon_sdf_payload_user_callback;
-void onAysncNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_beacon_sdf_payload_user_callback && event) {
-        on_nan_event_beacon_sdf_payload_user_callback(*event);
-    }
-}
-
-std::function<void(const NanDataPathRequestInd&)>
-    on_nan_event_data_path_request_user_callback;
-void onAysncNanEventDataPathRequest(NanDataPathRequestInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_data_path_request_user_callback && event) {
-        on_nan_event_data_path_request_user_callback(*event);
-    }
-}
-std::function<void(const NanDataPathConfirmInd&)>
-    on_nan_event_data_path_confirm_user_callback;
-void onAysncNanEventDataPathConfirm(NanDataPathConfirmInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_data_path_confirm_user_callback && event) {
-        on_nan_event_data_path_confirm_user_callback(*event);
-    }
-}
-
-std::function<void(const NanDataPathEndInd&)>
-    on_nan_event_data_path_end_user_callback;
-void onAysncNanEventDataPathEnd(NanDataPathEndInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_data_path_end_user_callback && event) {
-        on_nan_event_data_path_end_user_callback(*event);
-    }
-}
-
-std::function<void(const NanTransmitFollowupInd&)>
-    on_nan_event_transmit_follow_up_user_callback;
-void onAysncNanEventTransmitFollowUp(NanTransmitFollowupInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_transmit_follow_up_user_callback && event) {
-        on_nan_event_transmit_follow_up_user_callback(*event);
-    }
-}
-
-std::function<void(const NanRangeRequestInd&)>
-    on_nan_event_range_request_user_callback;
-void onAysncNanEventRangeRequest(NanRangeRequestInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_range_request_user_callback && event) {
-        on_nan_event_range_request_user_callback(*event);
-    }
-}
-
-std::function<void(const NanRangeReportInd&)>
-    on_nan_event_range_report_user_callback;
-void onAysncNanEventRangeReport(NanRangeReportInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_range_report_user_callback && event) {
-        on_nan_event_range_report_user_callback(*event);
-    }
-}
-
-std::function<void(const NanDataPathScheduleUpdateInd&)>
-    on_nan_event_schedule_update_user_callback;
-void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_nan_event_schedule_update_user_callback && event) {
-        on_nan_event_schedule_update_user_callback(*event);
-    }
-}
-
-// Callbacks for the various TWT operations.
-std::function<void(const TwtSetupResponse&)>
-    on_twt_event_setup_response_callback;
-void onAsyncTwtEventSetupResponse(TwtSetupResponse* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_twt_event_setup_response_callback && event) {
-        on_twt_event_setup_response_callback(*event);
-    }
-}
-
-std::function<void(const TwtTeardownCompletion&)>
-    on_twt_event_teardown_completion_callback;
-void onAsyncTwtEventTeardownCompletion(TwtTeardownCompletion* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_twt_event_teardown_completion_callback && event) {
-        on_twt_event_teardown_completion_callback(*event);
-    }
-}
-
-std::function<void(const TwtInfoFrameReceived&)>
-    on_twt_event_info_frame_received_callback;
-void onAsyncTwtEventInfoFrameReceived(TwtInfoFrameReceived* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_twt_event_info_frame_received_callback && event) {
-        on_twt_event_info_frame_received_callback(*event);
-    }
-}
-
-std::function<void(const TwtDeviceNotify&)> on_twt_event_device_notify_callback;
-void onAsyncTwtEventDeviceNotify(TwtDeviceNotify* event) {
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (on_twt_event_device_notify_callback && event) {
-        on_twt_event_device_notify_callback(*event);
-    }
-}
-
-// End of the free-standing "C" style callbacks.
-
-WifiLegacyHal::WifiLegacyHal(
-    const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
-    const wifi_hal_fn& fn, bool is_primary)
-    : global_func_table_(fn),
-      global_handle_(nullptr),
-      awaiting_event_loop_termination_(false),
-      is_started_(false),
-      iface_tool_(iface_tool),
-      is_primary_(is_primary) {}
-
-wifi_error WifiLegacyHal::initialize() {
-    LOG(DEBUG) << "Initialize legacy HAL";
-    // this now does nothing, since HAL function table is provided
-    // to the constructor
-    return WIFI_SUCCESS;
-}
-
-wifi_error WifiLegacyHal::start() {
-    // Ensure that we're starting in a good state.
-    CHECK(global_func_table_.wifi_initialize && !global_handle_ &&
-          iface_name_to_handle_.empty() && !awaiting_event_loop_termination_);
-    if (is_started_) {
-        LOG(DEBUG) << "Legacy HAL already started";
-        return WIFI_SUCCESS;
-    }
-    LOG(DEBUG) << "Waiting for the driver ready";
-    wifi_error status = global_func_table_.wifi_wait_for_driver_ready();
-    if (status == WIFI_ERROR_TIMED_OUT || status == WIFI_ERROR_UNKNOWN) {
-        LOG(ERROR) << "Failed or timed out awaiting driver ready";
-        return status;
-    }
-
-    if (is_primary_) {
-        property_set(kDriverPropName, "ok");
-
-        if (!iface_tool_.lock()->SetWifiUpState(true)) {
-            LOG(ERROR) << "Failed to set WiFi interface up";
-            return WIFI_ERROR_UNKNOWN;
-        }
-    }
-
-    LOG(DEBUG) << "Starting legacy HAL";
-    status = global_func_table_.wifi_initialize(&global_handle_);
-    if (status != WIFI_SUCCESS || !global_handle_) {
-        LOG(ERROR) << "Failed to retrieve global handle";
-        return status;
-    }
-    std::thread(&WifiLegacyHal::runEventLoop, this).detach();
-    status = retrieveIfaceHandles();
-    if (status != WIFI_SUCCESS || iface_name_to_handle_.empty()) {
-        LOG(ERROR) << "Failed to retrieve wlan interface handle";
-        return status;
-    }
-    LOG(DEBUG) << "Legacy HAL start complete";
-    is_started_ = true;
-    return WIFI_SUCCESS;
-}
-
-wifi_error WifiLegacyHal::stop(
-    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
-    const std::function<void()>& on_stop_complete_user_callback) {
-    if (!is_started_) {
-        LOG(DEBUG) << "Legacy HAL already stopped";
-        on_stop_complete_user_callback();
-        return WIFI_SUCCESS;
-    }
-    LOG(DEBUG) << "Stopping legacy HAL";
-    on_stop_complete_internal_callback = [on_stop_complete_user_callback,
-                                          this](wifi_handle handle) {
-        CHECK_EQ(global_handle_, handle) << "Handle mismatch";
-        LOG(INFO) << "Legacy HAL stop complete callback received";
-        // Invalidate all the internal pointers now that the HAL is
-        // stopped.
-        invalidate();
-        if (is_primary_) iface_tool_.lock()->SetWifiUpState(false);
-        on_stop_complete_user_callback();
-        is_started_ = false;
-    };
-    awaiting_event_loop_termination_ = true;
-    global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete);
-    const auto status = stop_wait_cv_.wait_for(
-        *lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs),
-        [this] { return !awaiting_event_loop_termination_; });
-    if (!status) {
-        LOG(ERROR) << "Legacy HAL stop failed or timed out";
-        return WIFI_ERROR_UNKNOWN;
-    }
-    LOG(DEBUG) << "Legacy HAL stop complete";
-    return WIFI_SUCCESS;
-}
-
-bool WifiLegacyHal::isStarted() { return is_started_; }
-
-wifi_error WifiLegacyHal::waitForDriverReady() {
-    return global_func_table_.wifi_wait_for_driver_ready();
-}
-
-std::pair<wifi_error, std::string> WifiLegacyHal::getDriverVersion(
-    const std::string& iface_name) {
-    std::array<char, kMaxVersionStringLength> buffer;
-    buffer.fill(0);
-    wifi_error status = global_func_table_.wifi_get_driver_version(
-        getIfaceHandle(iface_name), buffer.data(), buffer.size());
-    return {status, buffer.data()};
-}
-
-std::pair<wifi_error, std::string> WifiLegacyHal::getFirmwareVersion(
-    const std::string& iface_name) {
-    std::array<char, kMaxVersionStringLength> buffer;
-    buffer.fill(0);
-    wifi_error status = global_func_table_.wifi_get_firmware_version(
-        getIfaceHandle(iface_name), buffer.data(), buffer.size());
-    return {status, buffer.data()};
-}
-
-std::pair<wifi_error, std::vector<uint8_t>>
-WifiLegacyHal::requestDriverMemoryDump(const std::string& iface_name) {
-    std::vector<uint8_t> driver_dump;
-    on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer,
-                                                             int buffer_size) {
-        driver_dump.insert(driver_dump.end(),
-                           reinterpret_cast<uint8_t*>(buffer),
-                           reinterpret_cast<uint8_t*>(buffer) + buffer_size);
-    };
-    wifi_error status = global_func_table_.wifi_get_driver_memory_dump(
-        getIfaceHandle(iface_name), {onSyncDriverMemoryDump});
-    on_driver_memory_dump_internal_callback = nullptr;
-    return {status, std::move(driver_dump)};
-}
-
-std::pair<wifi_error, std::vector<uint8_t>>
-WifiLegacyHal::requestFirmwareMemoryDump(const std::string& iface_name) {
-    std::vector<uint8_t> firmware_dump;
-    on_firmware_memory_dump_internal_callback =
-        [&firmware_dump](char* buffer, int buffer_size) {
-            firmware_dump.insert(
-                firmware_dump.end(), reinterpret_cast<uint8_t*>(buffer),
-                reinterpret_cast<uint8_t*>(buffer) + buffer_size);
-        };
-    wifi_error status = global_func_table_.wifi_get_firmware_memory_dump(
-        getIfaceHandle(iface_name), {onSyncFirmwareMemoryDump});
-    on_firmware_memory_dump_internal_callback = nullptr;
-    return {status, std::move(firmware_dump)};
-}
-
-std::pair<wifi_error, uint64_t> WifiLegacyHal::getSupportedFeatureSet(
-    const std::string& iface_name) {
-    feature_set set = 0, chip_set = 0;
-    wifi_error status = WIFI_SUCCESS;
-
-    static_assert(sizeof(set) == sizeof(uint64_t),
-                  "Some feature_flags can not be represented in output");
-    wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
-
-    global_func_table_.wifi_get_chip_feature_set(
-        global_handle_, &chip_set); /* ignore error, chip_set will stay 0 */
-
-    if (iface_handle) {
-        status = global_func_table_.wifi_get_supported_feature_set(iface_handle,
-                                                                   &set);
-    }
-    return {status, static_cast<uint64_t>(set | chip_set)};
-}
-
-std::pair<wifi_error, PacketFilterCapabilities>
-WifiLegacyHal::getPacketFilterCapabilities(const std::string& iface_name) {
-    PacketFilterCapabilities caps;
-    wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
-        getIfaceHandle(iface_name), &caps.version, &caps.max_len);
-    return {status, caps};
-}
-
-wifi_error WifiLegacyHal::setPacketFilter(const std::string& iface_name,
-                                          const std::vector<uint8_t>& program) {
-    return global_func_table_.wifi_set_packet_filter(
-        getIfaceHandle(iface_name), program.data(), program.size());
-}
-
-std::pair<wifi_error, std::vector<uint8_t>>
-WifiLegacyHal::readApfPacketFilterData(const std::string& iface_name) {
-    PacketFilterCapabilities caps;
-    wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
-        getIfaceHandle(iface_name), &caps.version, &caps.max_len);
-    if (status != WIFI_SUCCESS) {
-        return {status, {}};
-    }
-
-    // Size the buffer to read the entire program & work memory.
-    std::vector<uint8_t> buffer(caps.max_len);
-
-    status = global_func_table_.wifi_read_packet_filter(
-        getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(),
-        buffer.size());
-    return {status, move(buffer)};
-}
-
-std::pair<wifi_error, wifi_gscan_capabilities>
-WifiLegacyHal::getGscanCapabilities(const std::string& iface_name) {
-    wifi_gscan_capabilities caps;
-    wifi_error status = global_func_table_.wifi_get_gscan_capabilities(
-        getIfaceHandle(iface_name), &caps);
-    return {status, caps};
-}
-
-wifi_error WifiLegacyHal::startGscan(
-    const std::string& iface_name, wifi_request_id id,
-    const wifi_scan_cmd_params& params,
-    const std::function<void(wifi_request_id)>& on_failure_user_callback,
-    const on_gscan_results_callback& on_results_user_callback,
-    const on_gscan_full_result_callback& on_full_result_user_callback) {
-    // If there is already an ongoing background scan, reject new scan requests.
-    if (on_gscan_event_internal_callback ||
-        on_gscan_full_result_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-
-    // This callback will be used to either trigger |on_results_user_callback|
-    // or |on_failure_user_callback|.
-    on_gscan_event_internal_callback =
-        [iface_name, on_failure_user_callback, on_results_user_callback, this](
-            wifi_request_id id, wifi_scan_event event) {
-            switch (event) {
-                case WIFI_SCAN_RESULTS_AVAILABLE:
-                case WIFI_SCAN_THRESHOLD_NUM_SCANS:
-                case WIFI_SCAN_THRESHOLD_PERCENT: {
-                    wifi_error status;
-                    std::vector<wifi_cached_scan_results> cached_scan_results;
-                    std::tie(status, cached_scan_results) =
-                        getGscanCachedResults(iface_name);
-                    if (status == WIFI_SUCCESS) {
-                        on_results_user_callback(id, cached_scan_results);
-                        return;
-                    }
-                    FALLTHROUGH_INTENDED;
-                }
-                // Fall through if failed. Failure to retrieve cached scan
-                // results should trigger a background scan failure.
-                case WIFI_SCAN_FAILED:
-                    on_failure_user_callback(id);
-                    on_gscan_event_internal_callback = nullptr;
-                    on_gscan_full_result_internal_callback = nullptr;
-                    return;
-            }
-            LOG(FATAL) << "Unexpected gscan event received: " << event;
-        };
-
-    on_gscan_full_result_internal_callback = [on_full_result_user_callback](
-                                                 wifi_request_id id,
-                                                 wifi_scan_result* result,
-                                                 uint32_t buckets_scanned) {
-        if (result) {
-            on_full_result_user_callback(id, result, buckets_scanned);
-        }
-    };
-
-    wifi_scan_result_handler handler = {onAsyncGscanFullResult,
-                                        onAsyncGscanEvent};
-    wifi_error status = global_func_table_.wifi_start_gscan(
-        id, getIfaceHandle(iface_name), params, handler);
-    if (status != WIFI_SUCCESS) {
-        on_gscan_event_internal_callback = nullptr;
-        on_gscan_full_result_internal_callback = nullptr;
-    }
-    return status;
-}
-
-wifi_error WifiLegacyHal::stopGscan(const std::string& iface_name,
-                                    wifi_request_id id) {
-    // If there is no an ongoing background scan, reject stop requests.
-    // TODO(b/32337212): This needs to be handled by the HIDL object because we
-    // need to return the NOT_STARTED error code.
-    if (!on_gscan_event_internal_callback &&
-        !on_gscan_full_result_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-    wifi_error status =
-        global_func_table_.wifi_stop_gscan(id, getIfaceHandle(iface_name));
-    // If the request Id is wrong, don't stop the ongoing background scan. Any
-    // other error should be treated as the end of background scan.
-    if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
-        on_gscan_event_internal_callback = nullptr;
-        on_gscan_full_result_internal_callback = nullptr;
-    }
-    return status;
-}
-
-std::pair<wifi_error, std::vector<uint32_t>>
-WifiLegacyHal::getValidFrequenciesForBand(const std::string& iface_name,
-                                          wifi_band band) {
-    static_assert(sizeof(uint32_t) >= sizeof(wifi_channel),
-                  "Wifi Channel cannot be represented in output");
-    std::vector<uint32_t> freqs;
-    freqs.resize(kMaxGscanFrequenciesForBand);
-    int32_t num_freqs = 0;
-    wifi_error status = global_func_table_.wifi_get_valid_channels(
-        getIfaceHandle(iface_name), band, freqs.size(),
-        reinterpret_cast<wifi_channel*>(freqs.data()), &num_freqs);
-    CHECK(num_freqs >= 0 &&
-          static_cast<uint32_t>(num_freqs) <= kMaxGscanFrequenciesForBand);
-    freqs.resize(num_freqs);
-    return {status, std::move(freqs)};
-}
-
-wifi_error WifiLegacyHal::setDfsFlag(const std::string& iface_name,
-                                     bool dfs_on) {
-    return global_func_table_.wifi_set_nodfs_flag(getIfaceHandle(iface_name),
-                                                  dfs_on ? 0 : 1);
-}
-
-wifi_error WifiLegacyHal::enableLinkLayerStats(const std::string& iface_name,
-                                               bool debug) {
-    wifi_link_layer_params params;
-    params.mpdu_size_threshold = kLinkLayerStatsDataMpduSizeThreshold;
-    params.aggressive_statistics_gathering = debug;
-    return global_func_table_.wifi_set_link_stats(getIfaceHandle(iface_name),
-                                                  params);
-}
-
-wifi_error WifiLegacyHal::disableLinkLayerStats(const std::string& iface_name) {
-    // TODO: Do we care about these responses?
-    uint32_t clear_mask_rsp;
-    uint8_t stop_rsp;
-    return global_func_table_.wifi_clear_link_stats(
-        getIfaceHandle(iface_name), 0xFFFFFFFF, &clear_mask_rsp, 1, &stop_rsp);
-}
-
-std::pair<wifi_error, LinkLayerStats> WifiLegacyHal::getLinkLayerStats(
-    const std::string& iface_name) {
-    LinkLayerStats link_stats{};
-    LinkLayerStats* link_stats_ptr = &link_stats;
-
-    on_link_layer_stats_result_internal_callback =
-        [&link_stats_ptr](wifi_request_id /* id */,
-                          wifi_iface_stat* iface_stats_ptr, int num_radios,
-                          wifi_radio_stat* radio_stats_ptr) {
-            wifi_radio_stat* l_radio_stats_ptr;
-            wifi_peer_info* l_peer_info_stats_ptr;
-
-            if (iface_stats_ptr != nullptr) {
-                link_stats_ptr->iface = *iface_stats_ptr;
-                l_peer_info_stats_ptr = iface_stats_ptr->peer_info;
-                for (uint32_t i = 0; i < iface_stats_ptr->num_peers; i++) {
-                    WifiPeerInfo peer;
-                    peer.peer_info = *l_peer_info_stats_ptr;
-                    if (l_peer_info_stats_ptr->num_rate > 0) {
-                        /* Copy the rate stats */
-                        peer.rate_stats.assign(
-                            l_peer_info_stats_ptr->rate_stats,
-                            l_peer_info_stats_ptr->rate_stats +
-                                l_peer_info_stats_ptr->num_rate);
-                    }
-                    peer.peer_info.num_rate = 0;
-                    link_stats_ptr->peers.push_back(peer);
-                    l_peer_info_stats_ptr =
-                        (wifi_peer_info*)((u8*)l_peer_info_stats_ptr +
-                                          sizeof(wifi_peer_info) +
-                                          (sizeof(wifi_rate_stat) *
-                                           l_peer_info_stats_ptr->num_rate));
-                }
-                link_stats_ptr->iface.num_peers = 0;
-            } else {
-                LOG(ERROR) << "Invalid iface stats in link layer stats";
-            }
-            if (num_radios <= 0 || radio_stats_ptr == nullptr) {
-                LOG(ERROR) << "Invalid radio stats in link layer stats";
-                return;
-            }
-            l_radio_stats_ptr = radio_stats_ptr;
-            for (int i = 0; i < num_radios; i++) {
-                LinkLayerRadioStats radio;
-
-                radio.stats = *l_radio_stats_ptr;
-                // Copy over the tx level array to the separate vector.
-                if (l_radio_stats_ptr->num_tx_levels > 0 &&
-                    l_radio_stats_ptr->tx_time_per_levels != nullptr) {
-                    radio.tx_time_per_levels.assign(
-                        l_radio_stats_ptr->tx_time_per_levels,
-                        l_radio_stats_ptr->tx_time_per_levels +
-                            l_radio_stats_ptr->num_tx_levels);
-                }
-                radio.stats.num_tx_levels = 0;
-                radio.stats.tx_time_per_levels = nullptr;
-                /* Copy over the channel stat to separate vector */
-                if (l_radio_stats_ptr->num_channels > 0) {
-                    /* Copy the channel stats */
-                    radio.channel_stats.assign(
-                        l_radio_stats_ptr->channels,
-                        l_radio_stats_ptr->channels +
-                            l_radio_stats_ptr->num_channels);
-                }
-                link_stats_ptr->radios.push_back(radio);
-                l_radio_stats_ptr =
-                    (wifi_radio_stat*)((u8*)l_radio_stats_ptr +
-                                       sizeof(wifi_radio_stat) +
-                                       (sizeof(wifi_channel_stat) *
-                                        l_radio_stats_ptr->num_channels));
-            }
-        };
-
-    wifi_error status = global_func_table_.wifi_get_link_stats(
-        0, getIfaceHandle(iface_name), {onSyncLinkLayerStatsResult});
-    on_link_layer_stats_result_internal_callback = nullptr;
-    return {status, link_stats};
-}
-
-wifi_error WifiLegacyHal::startRssiMonitoring(
-    const std::string& iface_name, wifi_request_id id, int8_t max_rssi,
-    int8_t min_rssi,
-    const on_rssi_threshold_breached_callback&
-        on_threshold_breached_user_callback) {
-    if (on_rssi_threshold_breached_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-    on_rssi_threshold_breached_internal_callback =
-        [on_threshold_breached_user_callback](wifi_request_id id,
-                                              uint8_t* bssid_ptr, int8_t rssi) {
-            if (!bssid_ptr) {
-                return;
-            }
-            std::array<uint8_t, 6> bssid_arr;
-            // |bssid_ptr| pointer is assumed to have 6 bytes for the mac
-            // address.
-            std::copy(bssid_ptr, bssid_ptr + 6, std::begin(bssid_arr));
-            on_threshold_breached_user_callback(id, bssid_arr, rssi);
-        };
-    wifi_error status = global_func_table_.wifi_start_rssi_monitoring(
-        id, getIfaceHandle(iface_name), max_rssi, min_rssi,
-        {onAsyncRssiThresholdBreached});
-    if (status != WIFI_SUCCESS) {
-        on_rssi_threshold_breached_internal_callback = nullptr;
-    }
-    return status;
-}
-
-wifi_error WifiLegacyHal::stopRssiMonitoring(const std::string& iface_name,
-                                             wifi_request_id id) {
-    if (!on_rssi_threshold_breached_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-    wifi_error status = global_func_table_.wifi_stop_rssi_monitoring(
-        id, getIfaceHandle(iface_name));
-    // If the request Id is wrong, don't stop the ongoing rssi monitoring. Any
-    // other error should be treated as the end of background scan.
-    if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
-        on_rssi_threshold_breached_internal_callback = nullptr;
-    }
-    return status;
-}
-
-std::pair<wifi_error, wifi_roaming_capabilities>
-WifiLegacyHal::getRoamingCapabilities(const std::string& iface_name) {
-    wifi_roaming_capabilities caps;
-    wifi_error status = global_func_table_.wifi_get_roaming_capabilities(
-        getIfaceHandle(iface_name), &caps);
-    return {status, caps};
-}
-
-wifi_error WifiLegacyHal::configureRoaming(const std::string& iface_name,
-                                           const wifi_roaming_config& config) {
-    wifi_roaming_config config_internal = config;
-    return global_func_table_.wifi_configure_roaming(getIfaceHandle(iface_name),
-                                                     &config_internal);
-}
-
-wifi_error WifiLegacyHal::enableFirmwareRoaming(const std::string& iface_name,
-                                                fw_roaming_state_t state) {
-    return global_func_table_.wifi_enable_firmware_roaming(
-        getIfaceHandle(iface_name), state);
-}
-
-wifi_error WifiLegacyHal::configureNdOffload(const std::string& iface_name,
-                                             bool enable) {
-    return global_func_table_.wifi_configure_nd_offload(
-        getIfaceHandle(iface_name), enable);
-}
-
-wifi_error WifiLegacyHal::startSendingOffloadedPacket(
-    const std::string& iface_name, uint32_t cmd_id, uint16_t ether_type,
-    const std::vector<uint8_t>& ip_packet_data,
-    const std::array<uint8_t, 6>& src_address,
-    const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms) {
-    std::vector<uint8_t> ip_packet_data_internal(ip_packet_data);
-    std::vector<uint8_t> src_address_internal(
-        src_address.data(), src_address.data() + src_address.size());
-    std::vector<uint8_t> dst_address_internal(
-        dst_address.data(), dst_address.data() + dst_address.size());
-    return global_func_table_.wifi_start_sending_offloaded_packet(
-        cmd_id, getIfaceHandle(iface_name), ether_type,
-        ip_packet_data_internal.data(), ip_packet_data_internal.size(),
-        src_address_internal.data(), dst_address_internal.data(), period_in_ms);
-}
-
-wifi_error WifiLegacyHal::stopSendingOffloadedPacket(
-    const std::string& iface_name, uint32_t cmd_id) {
-    return global_func_table_.wifi_stop_sending_offloaded_packet(
-        cmd_id, getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::selectTxPowerScenario(const std::string& iface_name,
-                                                wifi_power_scenario scenario) {
-    return global_func_table_.wifi_select_tx_power_scenario(
-        getIfaceHandle(iface_name), scenario);
-}
-
-wifi_error WifiLegacyHal::resetTxPowerScenario(const std::string& iface_name) {
-    return global_func_table_.wifi_reset_tx_power_scenario(
-        getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::setLatencyMode(const std::string& iface_name,
-                                         wifi_latency_mode mode) {
-    return global_func_table_.wifi_set_latency_mode(getIfaceHandle(iface_name),
-                                                    mode);
-}
-
-wifi_error WifiLegacyHal::setThermalMitigationMode(wifi_thermal_mode mode,
-                                                   uint32_t completion_window) {
-    return global_func_table_.wifi_set_thermal_mitigation_mode(
-        global_handle_, mode, completion_window);
-}
-
-wifi_error WifiLegacyHal::setDscpToAccessCategoryMapping(
-    uint32_t start, uint32_t end, uint32_t access_category) {
-    return global_func_table_.wifi_map_dscp_access_category(
-        global_handle_, start, end, access_category);
-}
-
-wifi_error WifiLegacyHal::resetDscpToAccessCategoryMapping() {
-    return global_func_table_.wifi_reset_dscp_mapping(global_handle_);
-}
-
-std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet(
-    const std::string& iface_name) {
-    uint32_t supported_feature_flags = 0;
-    wifi_error status = WIFI_SUCCESS;
-
-    wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
-
-    if (iface_handle) {
-        status = global_func_table_.wifi_get_logger_supported_feature_set(
-            iface_handle, &supported_feature_flags);
-    }
-    return {status, supported_feature_flags};
-}
-
-wifi_error WifiLegacyHal::startPktFateMonitoring(
-    const std::string& iface_name) {
-    return global_func_table_.wifi_start_pkt_fate_monitoring(
-        getIfaceHandle(iface_name));
-}
-
-std::pair<wifi_error, std::vector<wifi_tx_report>> WifiLegacyHal::getTxPktFates(
-    const std::string& iface_name) {
-    std::vector<wifi_tx_report> tx_pkt_fates;
-    tx_pkt_fates.resize(MAX_FATE_LOG_LEN);
-    size_t num_fates = 0;
-    wifi_error status = global_func_table_.wifi_get_tx_pkt_fates(
-        getIfaceHandle(iface_name), tx_pkt_fates.data(), tx_pkt_fates.size(),
-        &num_fates);
-    CHECK(num_fates <= MAX_FATE_LOG_LEN);
-    tx_pkt_fates.resize(num_fates);
-    return {status, std::move(tx_pkt_fates)};
-}
-
-std::pair<wifi_error, std::vector<wifi_rx_report>> WifiLegacyHal::getRxPktFates(
-    const std::string& iface_name) {
-    std::vector<wifi_rx_report> rx_pkt_fates;
-    rx_pkt_fates.resize(MAX_FATE_LOG_LEN);
-    size_t num_fates = 0;
-    wifi_error status = global_func_table_.wifi_get_rx_pkt_fates(
-        getIfaceHandle(iface_name), rx_pkt_fates.data(), rx_pkt_fates.size(),
-        &num_fates);
-    CHECK(num_fates <= MAX_FATE_LOG_LEN);
-    rx_pkt_fates.resize(num_fates);
-    return {status, std::move(rx_pkt_fates)};
-}
-
-std::pair<wifi_error, WakeReasonStats> WifiLegacyHal::getWakeReasonStats(
-    const std::string& iface_name) {
-    WakeReasonStats stats;
-    stats.cmd_event_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
-    stats.driver_fw_local_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
-
-    // This legacy struct needs separate memory to store the variable sized wake
-    // reason types.
-    stats.wake_reason_cnt.cmd_event_wake_cnt =
-        reinterpret_cast<int32_t*>(stats.cmd_event_wake_cnt.data());
-    stats.wake_reason_cnt.cmd_event_wake_cnt_sz =
-        stats.cmd_event_wake_cnt.size();
-    stats.wake_reason_cnt.cmd_event_wake_cnt_used = 0;
-    stats.wake_reason_cnt.driver_fw_local_wake_cnt =
-        reinterpret_cast<int32_t*>(stats.driver_fw_local_wake_cnt.data());
-    stats.wake_reason_cnt.driver_fw_local_wake_cnt_sz =
-        stats.driver_fw_local_wake_cnt.size();
-    stats.wake_reason_cnt.driver_fw_local_wake_cnt_used = 0;
-
-    wifi_error status = global_func_table_.wifi_get_wake_reason_stats(
-        getIfaceHandle(iface_name), &stats.wake_reason_cnt);
-
-    CHECK(
-        stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 &&
-        static_cast<uint32_t>(stats.wake_reason_cnt.cmd_event_wake_cnt_used) <=
-            kMaxWakeReasonStatsArraySize);
-    stats.cmd_event_wake_cnt.resize(
-        stats.wake_reason_cnt.cmd_event_wake_cnt_used);
-    stats.wake_reason_cnt.cmd_event_wake_cnt = nullptr;
-
-    CHECK(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used >= 0 &&
-          static_cast<uint32_t>(
-              stats.wake_reason_cnt.driver_fw_local_wake_cnt_used) <=
-              kMaxWakeReasonStatsArraySize);
-    stats.driver_fw_local_wake_cnt.resize(
-        stats.wake_reason_cnt.driver_fw_local_wake_cnt_used);
-    stats.wake_reason_cnt.driver_fw_local_wake_cnt = nullptr;
-
-    return {status, stats};
-}
-
-wifi_error WifiLegacyHal::registerRingBufferCallbackHandler(
-    const std::string& iface_name,
-    const on_ring_buffer_data_callback& on_user_data_callback) {
-    if (on_ring_buffer_data_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-    on_ring_buffer_data_internal_callback =
-        [on_user_data_callback](char* ring_name, char* buffer, int buffer_size,
-                                wifi_ring_buffer_status* status) {
-            if (status && buffer) {
-                std::vector<uint8_t> buffer_vector(
-                    reinterpret_cast<uint8_t*>(buffer),
-                    reinterpret_cast<uint8_t*>(buffer) + buffer_size);
-                on_user_data_callback(ring_name, buffer_vector, *status);
-            }
-        };
-    wifi_error status = global_func_table_.wifi_set_log_handler(
-        0, getIfaceHandle(iface_name), {onAsyncRingBufferData});
-    if (status != WIFI_SUCCESS) {
-        on_ring_buffer_data_internal_callback = nullptr;
-    }
-    return status;
-}
-
-wifi_error WifiLegacyHal::deregisterRingBufferCallbackHandler(
-    const std::string& iface_name) {
-    if (!on_ring_buffer_data_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-    on_ring_buffer_data_internal_callback = nullptr;
-    return global_func_table_.wifi_reset_log_handler(
-        0, getIfaceHandle(iface_name));
-}
-
-std::pair<wifi_error, std::vector<wifi_ring_buffer_status>>
-WifiLegacyHal::getRingBuffersStatus(const std::string& iface_name) {
-    std::vector<wifi_ring_buffer_status> ring_buffers_status;
-    ring_buffers_status.resize(kMaxRingBuffers);
-    uint32_t num_rings = kMaxRingBuffers;
-    wifi_error status = global_func_table_.wifi_get_ring_buffers_status(
-        getIfaceHandle(iface_name), &num_rings, ring_buffers_status.data());
-    CHECK(num_rings <= kMaxRingBuffers);
-    ring_buffers_status.resize(num_rings);
-    return {status, std::move(ring_buffers_status)};
-}
-
-wifi_error WifiLegacyHal::startRingBufferLogging(const std::string& iface_name,
-                                                 const std::string& ring_name,
-                                                 uint32_t verbose_level,
-                                                 uint32_t max_interval_sec,
-                                                 uint32_t min_data_size) {
-    return global_func_table_.wifi_start_logging(
-        getIfaceHandle(iface_name), verbose_level, 0, max_interval_sec,
-        min_data_size, makeCharVec(ring_name).data());
-}
-
-wifi_error WifiLegacyHal::getRingBufferData(const std::string& iface_name,
-                                            const std::string& ring_name) {
-    return global_func_table_.wifi_get_ring_data(getIfaceHandle(iface_name),
-                                                 makeCharVec(ring_name).data());
-}
-
-wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler(
-    const std::string& iface_name,
-    const on_error_alert_callback& on_user_alert_callback) {
-    if (on_error_alert_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-    on_error_alert_internal_callback = [on_user_alert_callback](
-                                           wifi_request_id id, char* buffer,
-                                           int buffer_size, int err_code) {
-        if (buffer) {
-            CHECK(id == 0);
-            on_user_alert_callback(
-                err_code,
-                std::vector<uint8_t>(
-                    reinterpret_cast<uint8_t*>(buffer),
-                    reinterpret_cast<uint8_t*>(buffer) + buffer_size));
-        }
-    };
-    wifi_error status = global_func_table_.wifi_set_alert_handler(
-        0, getIfaceHandle(iface_name), {onAsyncErrorAlert});
-    if (status != WIFI_SUCCESS) {
-        on_error_alert_internal_callback = nullptr;
-    }
-    return status;
-}
-
-wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler(
-    const std::string& iface_name) {
-    if (!on_error_alert_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-    on_error_alert_internal_callback = nullptr;
-    return global_func_table_.wifi_reset_alert_handler(
-        0, getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::registerRadioModeChangeCallbackHandler(
-    const std::string& iface_name,
-    const on_radio_mode_change_callback& on_user_change_callback) {
-    if (on_radio_mode_change_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-    on_radio_mode_change_internal_callback = [on_user_change_callback](
-                                                 wifi_request_id /* id */,
-                                                 uint32_t num_macs,
-                                                 wifi_mac_info* mac_infos_arr) {
-        if (num_macs > 0 && mac_infos_arr) {
-            std::vector<WifiMacInfo> mac_infos_vec;
-            for (uint32_t i = 0; i < num_macs; i++) {
-                WifiMacInfo mac_info;
-                mac_info.wlan_mac_id = mac_infos_arr[i].wlan_mac_id;
-                mac_info.mac_band = mac_infos_arr[i].mac_band;
-                for (int32_t j = 0; j < mac_infos_arr[i].num_iface; j++) {
-                    WifiIfaceInfo iface_info;
-                    iface_info.name = mac_infos_arr[i].iface_info[j].iface_name;
-                    iface_info.channel = mac_infos_arr[i].iface_info[j].channel;
-                    mac_info.iface_infos.push_back(iface_info);
-                }
-                mac_infos_vec.push_back(mac_info);
-            }
-            on_user_change_callback(mac_infos_vec);
-        }
-    };
-    wifi_error status = global_func_table_.wifi_set_radio_mode_change_handler(
-        0, getIfaceHandle(iface_name), {onAsyncRadioModeChange});
-    if (status != WIFI_SUCCESS) {
-        on_radio_mode_change_internal_callback = nullptr;
-    }
-    return status;
-}
-
-wifi_error WifiLegacyHal::registerSubsystemRestartCallbackHandler(
-    const on_subsystem_restart_callback& on_restart_callback) {
-    if (on_subsystem_restart_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-    on_subsystem_restart_internal_callback =
-        [on_restart_callback](const char* error) {
-            on_restart_callback(error);
-        };
-    wifi_error status = global_func_table_.wifi_set_subsystem_restart_handler(
-        global_handle_, {onAsyncSubsystemRestart});
-    if (status != WIFI_SUCCESS) {
-        on_subsystem_restart_internal_callback = nullptr;
-    }
-    return status;
-}
-
-wifi_error WifiLegacyHal::startRttRangeRequest(
-    const std::string& iface_name, wifi_request_id id,
-    const std::vector<wifi_rtt_config>& rtt_configs,
-    const on_rtt_results_callback& on_results_user_callback) {
-    if (on_rtt_results_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-
-    on_rtt_results_internal_callback =
-        [on_results_user_callback](wifi_request_id id, unsigned num_results,
-                                   wifi_rtt_result* rtt_results[]) {
-            if (num_results > 0 && !rtt_results) {
-                LOG(ERROR) << "Unexpected nullptr in RTT results";
-                return;
-            }
-            std::vector<const wifi_rtt_result*> rtt_results_vec;
-            std::copy_if(rtt_results, rtt_results + num_results,
-                         back_inserter(rtt_results_vec),
-                         [](wifi_rtt_result* rtt_result) {
-                             return rtt_result != nullptr;
-                         });
-            on_results_user_callback(id, rtt_results_vec);
-        };
-
-    std::vector<wifi_rtt_config> rtt_configs_internal(rtt_configs);
-    wifi_error status = global_func_table_.wifi_rtt_range_request(
-        id, getIfaceHandle(iface_name), rtt_configs.size(),
-        rtt_configs_internal.data(), {onAsyncRttResults});
-    if (status != WIFI_SUCCESS) {
-        on_rtt_results_internal_callback = nullptr;
-    }
-    return status;
-}
-
-wifi_error WifiLegacyHal::cancelRttRangeRequest(
-    const std::string& iface_name, wifi_request_id id,
-    const std::vector<std::array<uint8_t, 6>>& mac_addrs) {
-    if (!on_rtt_results_internal_callback) {
-        return WIFI_ERROR_NOT_AVAILABLE;
-    }
-    static_assert(sizeof(mac_addr) == sizeof(std::array<uint8_t, 6>),
-                  "MAC address size mismatch");
-    // TODO: How do we handle partial cancels (i.e only a subset of enabled mac
-    // addressed are cancelled).
-    std::vector<std::array<uint8_t, 6>> mac_addrs_internal(mac_addrs);
-    wifi_error status = global_func_table_.wifi_rtt_range_cancel(
-        id, getIfaceHandle(iface_name), mac_addrs.size(),
-        reinterpret_cast<mac_addr*>(mac_addrs_internal.data()));
-    // If the request Id is wrong, don't stop the ongoing range request. Any
-    // other error should be treated as the end of rtt ranging.
-    if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
-        on_rtt_results_internal_callback = nullptr;
-    }
-    return status;
-}
-
-std::pair<wifi_error, wifi_rtt_capabilities> WifiLegacyHal::getRttCapabilities(
-    const std::string& iface_name) {
-    wifi_rtt_capabilities rtt_caps;
-    wifi_error status = global_func_table_.wifi_get_rtt_capabilities(
-        getIfaceHandle(iface_name), &rtt_caps);
-    return {status, rtt_caps};
-}
-
-std::pair<wifi_error, wifi_rtt_responder> WifiLegacyHal::getRttResponderInfo(
-    const std::string& iface_name) {
-    wifi_rtt_responder rtt_responder;
-    wifi_error status = global_func_table_.wifi_rtt_get_responder_info(
-        getIfaceHandle(iface_name), &rtt_responder);
-    return {status, rtt_responder};
-}
-
-wifi_error WifiLegacyHal::enableRttResponder(
-    const std::string& iface_name, wifi_request_id id,
-    const wifi_channel_info& channel_hint, uint32_t max_duration_secs,
-    const wifi_rtt_responder& info) {
-    wifi_rtt_responder info_internal(info);
-    return global_func_table_.wifi_enable_responder(
-        id, getIfaceHandle(iface_name), channel_hint, max_duration_secs,
-        &info_internal);
-}
-
-wifi_error WifiLegacyHal::disableRttResponder(const std::string& iface_name,
-                                              wifi_request_id id) {
-    return global_func_table_.wifi_disable_responder(
-        id, getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::setRttLci(const std::string& iface_name,
-                                    wifi_request_id id,
-                                    const wifi_lci_information& info) {
-    wifi_lci_information info_internal(info);
-    return global_func_table_.wifi_set_lci(id, getIfaceHandle(iface_name),
-                                           &info_internal);
-}
-
-wifi_error WifiLegacyHal::setRttLcr(const std::string& iface_name,
-                                    wifi_request_id id,
-                                    const wifi_lcr_information& info) {
-    wifi_lcr_information info_internal(info);
-    return global_func_table_.wifi_set_lcr(id, getIfaceHandle(iface_name),
-                                           &info_internal);
-}
-
-wifi_error WifiLegacyHal::nanRegisterCallbackHandlers(
-    const std::string& iface_name, const NanCallbackHandlers& user_callbacks) {
-    on_nan_notify_response_user_callback = user_callbacks.on_notify_response;
-    on_nan_event_publish_terminated_user_callback =
-        user_callbacks.on_event_publish_terminated;
-    on_nan_event_match_user_callback = user_callbacks.on_event_match;
-    on_nan_event_match_expired_user_callback =
-        user_callbacks.on_event_match_expired;
-    on_nan_event_subscribe_terminated_user_callback =
-        user_callbacks.on_event_subscribe_terminated;
-    on_nan_event_followup_user_callback = user_callbacks.on_event_followup;
-    on_nan_event_disc_eng_event_user_callback =
-        user_callbacks.on_event_disc_eng_event;
-    on_nan_event_disabled_user_callback = user_callbacks.on_event_disabled;
-    on_nan_event_tca_user_callback = user_callbacks.on_event_tca;
-    on_nan_event_beacon_sdf_payload_user_callback =
-        user_callbacks.on_event_beacon_sdf_payload;
-    on_nan_event_data_path_request_user_callback =
-        user_callbacks.on_event_data_path_request;
-    on_nan_event_data_path_confirm_user_callback =
-        user_callbacks.on_event_data_path_confirm;
-    on_nan_event_data_path_end_user_callback =
-        user_callbacks.on_event_data_path_end;
-    on_nan_event_transmit_follow_up_user_callback =
-        user_callbacks.on_event_transmit_follow_up;
-    on_nan_event_range_request_user_callback =
-        user_callbacks.on_event_range_request;
-    on_nan_event_range_report_user_callback =
-        user_callbacks.on_event_range_report;
-    on_nan_event_schedule_update_user_callback =
-        user_callbacks.on_event_schedule_update;
-
-    return global_func_table_.wifi_nan_register_handler(
-        getIfaceHandle(iface_name),
-        {onAysncNanNotifyResponse, onAysncNanEventPublishReplied,
-         onAysncNanEventPublishTerminated, onAysncNanEventMatch,
-         onAysncNanEventMatchExpired, onAysncNanEventSubscribeTerminated,
-         onAysncNanEventFollowup, onAysncNanEventDiscEngEvent,
-         onAysncNanEventDisabled, onAysncNanEventTca,
-         onAysncNanEventBeaconSdfPayload, onAysncNanEventDataPathRequest,
-         onAysncNanEventDataPathConfirm, onAysncNanEventDataPathEnd,
-         onAysncNanEventTransmitFollowUp, onAysncNanEventRangeRequest,
-         onAysncNanEventRangeReport, onAsyncNanEventScheduleUpdate});
-}
-
-wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name,
-                                           transaction_id id,
-                                           const NanEnableRequest& msg) {
-    NanEnableRequest msg_internal(msg);
-    return global_func_table_.wifi_nan_enable_request(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanDisableRequest(const std::string& iface_name,
-                                            transaction_id id) {
-    return global_func_table_.wifi_nan_disable_request(
-        id, getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::nanPublishRequest(const std::string& iface_name,
-                                            transaction_id id,
-                                            const NanPublishRequest& msg) {
-    NanPublishRequest msg_internal(msg);
-    return global_func_table_.wifi_nan_publish_request(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanPublishCancelRequest(
-    const std::string& iface_name, transaction_id id,
-    const NanPublishCancelRequest& msg) {
-    NanPublishCancelRequest msg_internal(msg);
-    return global_func_table_.wifi_nan_publish_cancel_request(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanSubscribeRequest(const std::string& iface_name,
-                                              transaction_id id,
-                                              const NanSubscribeRequest& msg) {
-    NanSubscribeRequest msg_internal(msg);
-    return global_func_table_.wifi_nan_subscribe_request(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanSubscribeCancelRequest(
-    const std::string& iface_name, transaction_id id,
-    const NanSubscribeCancelRequest& msg) {
-    NanSubscribeCancelRequest msg_internal(msg);
-    return global_func_table_.wifi_nan_subscribe_cancel_request(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanTransmitFollowupRequest(
-    const std::string& iface_name, transaction_id id,
-    const NanTransmitFollowupRequest& msg) {
-    NanTransmitFollowupRequest msg_internal(msg);
-    return global_func_table_.wifi_nan_transmit_followup_request(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanStatsRequest(const std::string& iface_name,
-                                          transaction_id id,
-                                          const NanStatsRequest& msg) {
-    NanStatsRequest msg_internal(msg);
-    return global_func_table_.wifi_nan_stats_request(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanConfigRequest(const std::string& iface_name,
-                                           transaction_id id,
-                                           const NanConfigRequest& msg) {
-    NanConfigRequest msg_internal(msg);
-    return global_func_table_.wifi_nan_config_request(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanTcaRequest(const std::string& iface_name,
-                                        transaction_id id,
-                                        const NanTCARequest& msg) {
-    NanTCARequest msg_internal(msg);
-    return global_func_table_.wifi_nan_tca_request(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanBeaconSdfPayloadRequest(
-    const std::string& iface_name, transaction_id id,
-    const NanBeaconSdfPayloadRequest& msg) {
-    NanBeaconSdfPayloadRequest msg_internal(msg);
-    return global_func_table_.wifi_nan_beacon_sdf_payload_request(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-std::pair<wifi_error, NanVersion> WifiLegacyHal::nanGetVersion() {
-    NanVersion version;
-    wifi_error status =
-        global_func_table_.wifi_nan_get_version(global_handle_, &version);
-    return {status, version};
-}
-
-wifi_error WifiLegacyHal::nanGetCapabilities(const std::string& iface_name,
-                                             transaction_id id) {
-    return global_func_table_.wifi_nan_get_capabilities(
-        id, getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::nanDataInterfaceCreate(
-    const std::string& iface_name, transaction_id id,
-    const std::string& data_iface_name) {
-    return global_func_table_.wifi_nan_data_interface_create(
-        id, getIfaceHandle(iface_name), makeCharVec(data_iface_name).data());
-}
-
-wifi_error WifiLegacyHal::nanDataInterfaceDelete(
-    const std::string& iface_name, transaction_id id,
-    const std::string& data_iface_name) {
-    return global_func_table_.wifi_nan_data_interface_delete(
-        id, getIfaceHandle(iface_name), makeCharVec(data_iface_name).data());
-}
-
-wifi_error WifiLegacyHal::nanDataRequestInitiator(
-    const std::string& iface_name, transaction_id id,
-    const NanDataPathInitiatorRequest& msg) {
-    NanDataPathInitiatorRequest msg_internal(msg);
-    return global_func_table_.wifi_nan_data_request_initiator(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanDataIndicationResponse(
-    const std::string& iface_name, transaction_id id,
-    const NanDataPathIndicationResponse& msg) {
-    NanDataPathIndicationResponse msg_internal(msg);
-    return global_func_table_.wifi_nan_data_indication_response(
-        id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-typedef struct {
-    u8 num_ndp_instances;
-    NanDataPathId ndp_instance_id;
-} NanDataPathEndSingleNdpIdRequest;
-
-wifi_error WifiLegacyHal::nanDataEnd(const std::string& iface_name,
-                                     transaction_id id,
-                                     uint32_t ndpInstanceId) {
-    NanDataPathEndSingleNdpIdRequest msg;
-    msg.num_ndp_instances = 1;
-    msg.ndp_instance_id = ndpInstanceId;
-    wifi_error status = global_func_table_.wifi_nan_data_end(
-        id, getIfaceHandle(iface_name), (NanDataPathEndRequest*)&msg);
-    return status;
-}
-
-wifi_error WifiLegacyHal::setCountryCode(const std::string& iface_name,
-                                         std::array<int8_t, 2> code) {
-    std::string code_str(code.data(), code.data() + code.size());
-    return global_func_table_.wifi_set_country_code(getIfaceHandle(iface_name),
-                                                    code_str.c_str());
-}
-
-wifi_error WifiLegacyHal::retrieveIfaceHandles() {
-    wifi_interface_handle* iface_handles = nullptr;
-    int num_iface_handles = 0;
-    wifi_error status = global_func_table_.wifi_get_ifaces(
-        global_handle_, &num_iface_handles, &iface_handles);
-    if (status != WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to enumerate interface handles";
-        return status;
-    }
-    iface_name_to_handle_.clear();
-    for (int i = 0; i < num_iface_handles; ++i) {
-        std::array<char, IFNAMSIZ> iface_name_arr = {};
-        status = global_func_table_.wifi_get_iface_name(
-            iface_handles[i], iface_name_arr.data(), iface_name_arr.size());
-        if (status != WIFI_SUCCESS) {
-            LOG(WARNING) << "Failed to get interface handle name";
-            continue;
-        }
-        // Assuming the interface name is null terminated since the legacy HAL
-        // API does not return a size.
-        std::string iface_name(iface_name_arr.data());
-        LOG(INFO) << "Adding interface handle for " << iface_name;
-        iface_name_to_handle_[iface_name] = iface_handles[i];
-    }
-    return WIFI_SUCCESS;
-}
-
-wifi_interface_handle WifiLegacyHal::getIfaceHandle(
-    const std::string& iface_name) {
-    const auto iface_handle_iter = iface_name_to_handle_.find(iface_name);
-    if (iface_handle_iter == iface_name_to_handle_.end()) {
-        LOG(ERROR) << "Unknown iface name: " << iface_name;
-        return nullptr;
-    }
-    return iface_handle_iter->second;
-}
-
-void WifiLegacyHal::runEventLoop() {
-    LOG(DEBUG) << "Starting legacy HAL event loop";
-    global_func_table_.wifi_event_loop(global_handle_);
-    const auto lock = hidl_sync_util::acquireGlobalLock();
-    if (!awaiting_event_loop_termination_) {
-        LOG(FATAL)
-            << "Legacy HAL event loop terminated, but HAL was not stopping";
-    }
-    LOG(DEBUG) << "Legacy HAL event loop terminated";
-    awaiting_event_loop_termination_ = false;
-    stop_wait_cv_.notify_one();
-}
-
-std::pair<wifi_error, std::vector<wifi_cached_scan_results>>
-WifiLegacyHal::getGscanCachedResults(const std::string& iface_name) {
-    std::vector<wifi_cached_scan_results> cached_scan_results;
-    cached_scan_results.resize(kMaxCachedGscanResults);
-    int32_t num_results = 0;
-    wifi_error status = global_func_table_.wifi_get_cached_gscan_results(
-        getIfaceHandle(iface_name), true /* always flush */,
-        cached_scan_results.size(), cached_scan_results.data(), &num_results);
-    CHECK(num_results >= 0 &&
-          static_cast<uint32_t>(num_results) <= kMaxCachedGscanResults);
-    cached_scan_results.resize(num_results);
-    // Check for invalid IE lengths in these cached scan results and correct it.
-    for (auto& cached_scan_result : cached_scan_results) {
-        int num_scan_results = cached_scan_result.num_results;
-        for (int i = 0; i < num_scan_results; i++) {
-            auto& scan_result = cached_scan_result.results[i];
-            if (scan_result.ie_length > 0) {
-                LOG(DEBUG) << "Cached scan result has non-zero IE length "
-                           << scan_result.ie_length;
-                scan_result.ie_length = 0;
-            }
-        }
-    }
-    return {status, std::move(cached_scan_results)};
-}
-
-wifi_error WifiLegacyHal::createVirtualInterface(const std::string& ifname,
-                                                 wifi_interface_type iftype) {
-    // Create the interface if it doesn't exist. If interface already exist,
-    // Vendor Hal should return WIFI_SUCCESS.
-    wifi_error status = global_func_table_.wifi_virtual_interface_create(
-        global_handle_, ifname.c_str(), iftype);
-    return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status);
-}
-
-wifi_error WifiLegacyHal::deleteVirtualInterface(const std::string& ifname) {
-    // Delete the interface if it was created dynamically.
-    wifi_error status = global_func_table_.wifi_virtual_interface_delete(
-        global_handle_, ifname.c_str());
-    return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status);
-}
-
-wifi_error WifiLegacyHal::handleVirtualInterfaceCreateOrDeleteStatus(
-    const std::string& ifname, wifi_error status) {
-    if (status == WIFI_SUCCESS) {
-        // refresh list of handlers now.
-        status = retrieveIfaceHandles();
-    } else if (status == WIFI_ERROR_NOT_SUPPORTED) {
-        // Vendor hal does not implement this API. Such vendor implementations
-        // are expected to create / delete interface by other means.
-
-        // check if interface exists.
-        if (if_nametoindex(ifname.c_str())) {
-            status = retrieveIfaceHandles();
-        }
-    }
-    return status;
-}
-
-wifi_error WifiLegacyHal::getSupportedIfaceName(uint32_t iface_type,
-                                                std::string& ifname) {
-    std::array<char, IFNAMSIZ> buffer;
-
-    wifi_error res = global_func_table_.wifi_get_supported_iface_name(
-        global_handle_, (uint32_t)iface_type, buffer.data(), buffer.size());
-    if (res == WIFI_SUCCESS) ifname = buffer.data();
-
-    return res;
-}
-
-wifi_error WifiLegacyHal::multiStaSetPrimaryConnection(
-    const std::string& ifname) {
-    return global_func_table_.wifi_multi_sta_set_primary_connection(
-        global_handle_, getIfaceHandle(ifname));
-}
-
-wifi_error WifiLegacyHal::multiStaSetUseCase(wifi_multi_sta_use_case use_case) {
-    return global_func_table_.wifi_multi_sta_set_use_case(global_handle_,
-                                                          use_case);
-}
-
-wifi_error WifiLegacyHal::setCoexUnsafeChannels(
-    std::vector<wifi_coex_unsafe_channel> unsafe_channels,
-    uint32_t restrictions) {
-    return global_func_table_.wifi_set_coex_unsafe_channels(
-        global_handle_, unsafe_channels.size(), unsafe_channels.data(),
-        restrictions);
-}
-
-wifi_error WifiLegacyHal::setVoipMode(const std::string& iface_name,
-                                      wifi_voip_mode mode) {
-    return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name),
-                                                 mode);
-}
-
-wifi_error WifiLegacyHal::twtRegisterHandler(
-    const std::string& iface_name, const TwtCallbackHandlers& user_callbacks) {
-    on_twt_event_setup_response_callback = user_callbacks.on_setup_response;
-    on_twt_event_teardown_completion_callback =
-        user_callbacks.on_teardown_completion;
-    on_twt_event_info_frame_received_callback =
-        user_callbacks.on_info_frame_received;
-    on_twt_event_device_notify_callback = user_callbacks.on_device_notify;
-
-    return global_func_table_.wifi_twt_register_handler(
-        getIfaceHandle(iface_name),
-        {onAsyncTwtEventSetupResponse, onAsyncTwtEventTeardownCompletion,
-         onAsyncTwtEventInfoFrameReceived, onAsyncTwtEventDeviceNotify});
-}
-
-std::pair<wifi_error, TwtCapabilitySet> WifiLegacyHal::twtGetCapability(
-    const std::string& iface_name) {
-    TwtCapabilitySet capSet;
-    wifi_error status = global_func_table_.wifi_twt_get_capability(
-        getIfaceHandle(iface_name), &capSet);
-    return {status, capSet};
-}
-
-wifi_error WifiLegacyHal::twtSetupRequest(const std::string& iface_name,
-                                          const TwtSetupRequest& msg) {
-    TwtSetupRequest msgInternal(msg);
-    return global_func_table_.wifi_twt_setup_request(getIfaceHandle(iface_name),
-                                                     &msgInternal);
-}
-
-wifi_error WifiLegacyHal::twtTearDownRequest(const std::string& iface_name,
-                                             const TwtTeardownRequest& msg) {
-    TwtTeardownRequest msgInternal(msg);
-    return global_func_table_.wifi_twt_teardown_request(
-        getIfaceHandle(iface_name), &msgInternal);
-}
-
-wifi_error WifiLegacyHal::twtInfoFrameRequest(const std::string& iface_name,
-                                              const TwtInfoFrameRequest& msg) {
-    TwtInfoFrameRequest msgInternal(msg);
-    return global_func_table_.wifi_twt_info_frame_request(
-        getIfaceHandle(iface_name), &msgInternal);
-}
-
-std::pair<wifi_error, TwtStats> WifiLegacyHal::twtGetStats(
-    const std::string& iface_name, uint8_t configId) {
-    TwtStats stats;
-    wifi_error status = global_func_table_.wifi_twt_get_stats(
-        getIfaceHandle(iface_name), configId, &stats);
-    return {status, stats};
-}
-
-wifi_error WifiLegacyHal::twtClearStats(const std::string& iface_name,
-                                        uint8_t configId) {
-    return global_func_table_.wifi_twt_clear_stats(getIfaceHandle(iface_name),
-                                                   configId);
-}
-
-wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name,
-                                        uint32_t multiplier) {
-    return global_func_table_.wifi_set_dtim_config(getIfaceHandle(iface_name),
-                                                   multiplier);
-}
-
-std::pair<wifi_error, std::vector<wifi_usable_channel>>
-WifiLegacyHal::getUsableChannels(uint32_t band_mask, uint32_t iface_mode_mask,
-                                 uint32_t filter_mask) {
-    std::vector<wifi_usable_channel> channels;
-    channels.resize(kMaxWifiUsableChannels);
-    uint32_t size = 0;
-    wifi_error status = global_func_table_.wifi_get_usable_channels(
-        global_handle_, band_mask, iface_mode_mask, filter_mask,
-        channels.size(), &size,
-        reinterpret_cast<wifi_usable_channel*>(channels.data()));
-    CHECK(size >= 0 && size <= kMaxWifiUsableChannels);
-    channels.resize(size);
-    return {status, std::move(channels)};
-}
-
-wifi_error WifiLegacyHal::triggerSubsystemRestart() {
-    return global_func_table_.wifi_trigger_subsystem_restart(global_handle_);
-}
-
-void WifiLegacyHal::invalidate() {
-    global_handle_ = nullptr;
-    iface_name_to_handle_.clear();
-    on_driver_memory_dump_internal_callback = nullptr;
-    on_firmware_memory_dump_internal_callback = nullptr;
-    on_gscan_event_internal_callback = nullptr;
-    on_gscan_full_result_internal_callback = nullptr;
-    on_link_layer_stats_result_internal_callback = nullptr;
-    on_rssi_threshold_breached_internal_callback = nullptr;
-    on_ring_buffer_data_internal_callback = nullptr;
-    on_error_alert_internal_callback = nullptr;
-    on_radio_mode_change_internal_callback = nullptr;
-    on_subsystem_restart_internal_callback = nullptr;
-    on_rtt_results_internal_callback = nullptr;
-    on_nan_notify_response_user_callback = nullptr;
-    on_nan_event_publish_terminated_user_callback = nullptr;
-    on_nan_event_match_user_callback = nullptr;
-    on_nan_event_match_expired_user_callback = nullptr;
-    on_nan_event_subscribe_terminated_user_callback = nullptr;
-    on_nan_event_followup_user_callback = nullptr;
-    on_nan_event_disc_eng_event_user_callback = nullptr;
-    on_nan_event_disabled_user_callback = nullptr;
-    on_nan_event_tca_user_callback = nullptr;
-    on_nan_event_beacon_sdf_payload_user_callback = nullptr;
-    on_nan_event_data_path_request_user_callback = nullptr;
-    on_nan_event_data_path_confirm_user_callback = nullptr;
-    on_nan_event_data_path_end_user_callback = nullptr;
-    on_nan_event_transmit_follow_up_user_callback = nullptr;
-    on_nan_event_range_request_user_callback = nullptr;
-    on_nan_event_range_report_user_callback = nullptr;
-    on_nan_event_schedule_update_user_callback = nullptr;
-    on_twt_event_setup_response_callback = nullptr;
-    on_twt_event_teardown_completion_callback = nullptr;
-    on_twt_event_info_frame_received_callback = nullptr;
-    on_twt_event_device_notify_callback = nullptr;
-}
-
-}  // namespace legacy_hal
-}  // namespace implementation
-}  // namespace V1_5
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.5/default/wifi_nan_iface.cpp b/wifi/1.5/default/wifi_nan_iface.cpp
deleted file mode 100644
index 0cc6cd5..0000000
--- a/wifi/1.5/default/wifi_nan_iface.cpp
+++ /dev/null
@@ -1,1003 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_nan_iface.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_5 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiNanIface::WifiNanIface(
-    const std::string& ifname, bool is_dedicated_iface,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
-    const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
-    : ifname_(ifname),
-      is_dedicated_iface_(is_dedicated_iface),
-      legacy_hal_(legacy_hal),
-      iface_util_(iface_util),
-      is_valid_(true) {
-    if (is_dedicated_iface_) {
-        // If using a dedicated iface, set the iface up first.
-        if (!iface_util_.lock()->setUpState(ifname_, true)) {
-            // Fatal failure, invalidate the iface object.
-            invalidate();
-            return;
-        }
-    }
-    // Register all the callbacks here. these should be valid for the lifetime
-    // of the object. Whenever the mode changes legacy HAL will remove
-    // all of these callbacks.
-    legacy_hal::NanCallbackHandlers callback_handlers;
-    android::wp<WifiNanIface> weak_ptr_this(this);
-
-    // Callback for response.
-    callback_handlers
-        .on_notify_response = [weak_ptr_this](
-                                  legacy_hal::transaction_id id,
-                                  const legacy_hal::NanResponseMsg& msg) {
-        const auto shared_ptr_this = weak_ptr_this.promote();
-        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-            LOG(ERROR) << "Callback invoked on an invalid object";
-            return;
-        }
-        WifiNanStatus wifiNanStatus;
-        if (!hidl_struct_util::convertLegacyNanResponseHeaderToHidl(
-                msg, &wifiNanStatus)) {
-            LOG(ERROR) << "Failed to convert nan response header";
-            return;
-        }
-
-        switch (msg.response_type) {
-            case legacy_hal::NAN_RESPONSE_ENABLED: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback->notifyEnableResponse(id, wifiNanStatus)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_RESPONSE_DISABLED: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback->notifyDisableResponse(id, wifiNanStatus)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_RESPONSE_PUBLISH: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback
-                             ->notifyStartPublishResponse(
-                                 id, wifiNanStatus,
-                                 msg.body.publish_response.publish_id)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_RESPONSE_PUBLISH_CANCEL: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback->notifyStopPublishResponse(id, wifiNanStatus)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_RESPONSE_TRANSMIT_FOLLOWUP: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback
-                             ->notifyTransmitFollowupResponse(id, wifiNanStatus)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_RESPONSE_SUBSCRIBE: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback
-                             ->notifyStartSubscribeResponse(
-                                 id, wifiNanStatus,
-                                 msg.body.subscribe_response.subscribe_id)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_RESPONSE_SUBSCRIBE_CANCEL: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback
-                             ->notifyStopSubscribeResponse(id, wifiNanStatus)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_RESPONSE_CONFIG: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback->notifyConfigResponse(id, wifiNanStatus)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_GET_CAPABILITIES: {
-                NanCapabilities hidl_struct;
-                if (!hidl_struct_util::
-                        convertLegacyNanCapabilitiesResponseToHidl(
-                            msg.body.nan_capabilities, &hidl_struct)) {
-                    LOG(ERROR) << "Failed to convert nan capabilities response";
-                    return;
-                }
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks_1_5()) {
-                    if (!callback
-                             ->notifyCapabilitiesResponse_1_5(id, wifiNanStatus,
-                                                              hidl_struct)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_DP_INTERFACE_CREATE: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback
-                             ->notifyCreateDataInterfaceResponse(id,
-                                                                 wifiNanStatus)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_DP_INTERFACE_DELETE: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback
-                             ->notifyDeleteDataInterfaceResponse(id,
-                                                                 wifiNanStatus)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_DP_INITIATOR_RESPONSE: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback
-                             ->notifyInitiateDataPathResponse(
-                                 id, wifiNanStatus,
-                                 msg.body.data_request_response.ndp_instance_id)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_DP_RESPONDER_RESPONSE: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback
-                             ->notifyRespondToDataPathIndicationResponse(
-                                 id, wifiNanStatus)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_DP_END: {
-                for (const auto& callback :
-                     shared_ptr_this->getEventCallbacks()) {
-                    if (!callback
-                             ->notifyTerminateDataPathResponse(id,
-                                                               wifiNanStatus)
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-                break;
-            }
-            case legacy_hal::NAN_RESPONSE_BEACON_SDF_PAYLOAD:
-            /* fall through */
-            case legacy_hal::NAN_RESPONSE_TCA:
-            /* fall through */
-            case legacy_hal::NAN_RESPONSE_STATS:
-            /* fall through */
-            case legacy_hal::NAN_RESPONSE_ERROR:
-            /* fall through */
-            default:
-                LOG(ERROR) << "Unknown or unhandled response type: "
-                           << msg.response_type;
-                return;
-        }
-    };
-
-    callback_handlers.on_event_disc_eng_event =
-        [weak_ptr_this](const legacy_hal::NanDiscEngEventInd& msg) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            NanClusterEventInd hidl_struct;
-            // event types defined identically - hence can be cast
-            hidl_struct.eventType = (NanClusterEventType)msg.event_type;
-            hidl_struct.addr = msg.data.mac_addr.addr;
-
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->eventClusterEvent(hidl_struct).isOk()) {
-                    LOG(ERROR) << "Failed to invoke the callback";
-                }
-            }
-        };
-
-    callback_handlers.on_event_disabled =
-        [weak_ptr_this](const legacy_hal::NanDisabledInd& msg) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            WifiNanStatus status;
-            hidl_struct_util::convertToWifiNanStatus(
-                msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status);
-
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->eventDisabled(status).isOk()) {
-                    LOG(ERROR) << "Failed to invoke the callback";
-                }
-            }
-        };
-
-    callback_handlers.on_event_publish_terminated =
-        [weak_ptr_this](const legacy_hal::NanPublishTerminatedInd& msg) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            WifiNanStatus status;
-            hidl_struct_util::convertToWifiNanStatus(
-                msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status);
-
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->eventPublishTerminated(msg.publish_id, status)
-                         .isOk()) {
-                    LOG(ERROR) << "Failed to invoke the callback";
-                }
-            }
-        };
-
-    callback_handlers.on_event_subscribe_terminated =
-        [weak_ptr_this](const legacy_hal::NanSubscribeTerminatedInd& msg) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            WifiNanStatus status;
-            hidl_struct_util::convertToWifiNanStatus(
-                msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status);
-
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback
-                         ->eventSubscribeTerminated(msg.subscribe_id, status)
-                         .isOk()) {
-                    LOG(ERROR) << "Failed to invoke the callback";
-                }
-            }
-        };
-
-    callback_handlers.on_event_match =
-        [weak_ptr_this](const legacy_hal::NanMatchInd& msg) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            NanMatchInd hidl_struct;
-            if (!hidl_struct_util::convertLegacyNanMatchIndToHidl(
-                    msg, &hidl_struct)) {
-                LOG(ERROR) << "Failed to convert nan capabilities response";
-                return;
-            }
-
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->eventMatch(hidl_struct).isOk()) {
-                    LOG(ERROR) << "Failed to invoke the callback";
-                }
-            }
-        };
-
-    callback_handlers.on_event_match_expired =
-        [weak_ptr_this](const legacy_hal::NanMatchExpiredInd& msg) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback
-                         ->eventMatchExpired(msg.publish_subscribe_id,
-                                             msg.requestor_instance_id)
-                         .isOk()) {
-                    LOG(ERROR) << "Failed to invoke the callback";
-                }
-            }
-        };
-
-    callback_handlers.on_event_followup =
-        [weak_ptr_this](const legacy_hal::NanFollowupInd& msg) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            NanFollowupReceivedInd hidl_struct;
-            if (!hidl_struct_util::convertLegacyNanFollowupIndToHidl(
-                    msg, &hidl_struct)) {
-                LOG(ERROR) << "Failed to convert nan capabilities response";
-                return;
-            }
-
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->eventFollowupReceived(hidl_struct).isOk()) {
-                    LOG(ERROR) << "Failed to invoke the callback";
-                }
-            }
-        };
-
-    callback_handlers.on_event_transmit_follow_up =
-        [weak_ptr_this](const legacy_hal::NanTransmitFollowupInd& msg) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            WifiNanStatus status;
-            hidl_struct_util::convertToWifiNanStatus(
-                msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status);
-
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->eventTransmitFollowup(msg.id, status).isOk()) {
-                    LOG(ERROR) << "Failed to invoke the callback";
-                }
-            }
-        };
-
-    callback_handlers.on_event_data_path_request =
-        [weak_ptr_this](const legacy_hal::NanDataPathRequestInd& msg) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            NanDataPathRequestInd hidl_struct;
-            if (!hidl_struct_util::convertLegacyNanDataPathRequestIndToHidl(
-                    msg, &hidl_struct)) {
-                LOG(ERROR) << "Failed to convert nan capabilities response";
-                return;
-            }
-
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->eventDataPathRequest(hidl_struct).isOk()) {
-                    LOG(ERROR) << "Failed to invoke the callback";
-                }
-            }
-        };
-
-    callback_handlers.on_event_data_path_confirm =
-        [weak_ptr_this](const legacy_hal::NanDataPathConfirmInd& msg) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            V1_2::NanDataPathConfirmInd hidl_struct;
-            if (!hidl_struct_util::convertLegacyNanDataPathConfirmIndToHidl(
-                    msg, &hidl_struct)) {
-                LOG(ERROR) << "Failed to convert nan capabilities response";
-                return;
-            }
-
-            for (const auto& callback :
-                 shared_ptr_this->getEventCallbacks_1_2()) {
-                if (!callback->eventDataPathConfirm_1_2(hidl_struct).isOk()) {
-                    LOG(ERROR) << "Failed to invoke the callback";
-                }
-            }
-        };
-
-    callback_handlers.on_event_data_path_end =
-        [weak_ptr_this](const legacy_hal::NanDataPathEndInd& msg) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                for (int i = 0; i < msg.num_ndp_instances; ++i) {
-                    if (!callback
-                             ->eventDataPathTerminated(msg.ndp_instance_id[i])
-                             .isOk()) {
-                        LOG(ERROR) << "Failed to invoke the callback";
-                    }
-                }
-            }
-        };
-
-    callback_handlers.on_event_beacon_sdf_payload =
-        [weak_ptr_this](const legacy_hal::NanBeaconSdfPayloadInd& /* msg */) {
-            LOG(ERROR) << "on_event_beacon_sdf_payload - should not be called";
-        };
-
-    callback_handlers.on_event_range_request =
-        [weak_ptr_this](const legacy_hal::NanRangeRequestInd& /* msg */) {
-            LOG(ERROR) << "on_event_range_request - should not be called";
-        };
-
-    callback_handlers.on_event_range_report =
-        [weak_ptr_this](const legacy_hal::NanRangeReportInd& /* msg */) {
-            LOG(ERROR) << "on_event_range_report - should not be called";
-        };
-
-    callback_handlers
-        .on_event_schedule_update = [weak_ptr_this](
-                                        const legacy_hal::
-                                            NanDataPathScheduleUpdateInd& msg) {
-        const auto shared_ptr_this = weak_ptr_this.promote();
-        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-            LOG(ERROR) << "Callback invoked on an invalid object";
-            return;
-        }
-        V1_2::NanDataPathScheduleUpdateInd hidl_struct;
-        if (!hidl_struct_util::convertLegacyNanDataPathScheduleUpdateIndToHidl(
-                msg, &hidl_struct)) {
-            LOG(ERROR) << "Failed to convert nan capabilities response";
-            return;
-        }
-
-        for (const auto& callback : shared_ptr_this->getEventCallbacks_1_2()) {
-            if (!callback->eventDataPathScheduleUpdate(hidl_struct).isOk()) {
-                LOG(ERROR) << "Failed to invoke the callback";
-            }
-        }
-    };
-
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanRegisterCallbackHandlers(ifname_,
-                                                        callback_handlers);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to register nan callbacks. Invalidating object";
-        invalidate();
-    }
-
-    // Register for iface state toggle events.
-    iface_util::IfaceEventHandlers event_handlers = {};
-    event_handlers.on_state_toggle_off_on =
-        [weak_ptr_this](const std::string& /* iface_name */) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            // Tell framework that NAN has been disabled.
-            WifiNanStatus status = {
-                NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->eventDisabled(status).isOk()) {
-                    LOG(ERROR) << "Failed to invoke the callback";
-                }
-            }
-        };
-    iface_util_.lock()->registerIfaceEventHandlers(ifname_, event_handlers);
-}
-
-void WifiNanIface::invalidate() {
-    if (!isValid()) {
-        return;
-    }
-    // send commands to HAL to actually disable and destroy interfaces
-    legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF);
-    legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0");
-    legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1");
-    iface_util_.lock()->unregisterIfaceEventHandlers(ifname_);
-    legacy_hal_.reset();
-    event_cb_handler_.invalidate();
-    event_cb_handler_1_2_.invalidate();
-    event_cb_handler_1_5_.invalidate();
-    is_valid_ = false;
-    if (is_dedicated_iface_) {
-        // If using a dedicated iface, set the iface down.
-        iface_util_.lock()->setUpState(ifname_, false);
-    }
-}
-
-bool WifiNanIface::isValid() { return is_valid_; }
-
-std::string WifiNanIface::getName() { return ifname_; }
-
-std::set<sp<V1_0::IWifiNanIfaceEventCallback>>
-WifiNanIface::getEventCallbacks() {
-    return event_cb_handler_.getCallbacks();
-}
-
-std::set<sp<V1_2::IWifiNanIfaceEventCallback>>
-WifiNanIface::getEventCallbacks_1_2() {
-    return event_cb_handler_1_2_.getCallbacks();
-}
-
-std::set<sp<IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks_1_5() {
-    return event_cb_handler_1_5_.getCallbacks();
-}
-
-Return<void> WifiNanIface::getName(getName_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::getNameInternal, hidl_status_cb);
-}
-
-Return<void> WifiNanIface::getType(getType_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::getTypeInternal, hidl_status_cb);
-}
-
-Return<void> WifiNanIface::registerEventCallback(
-    const sp<V1_0::IWifiNanIfaceEventCallback>& callback,
-    registerEventCallback_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::registerEventCallbackInternal,
-                           hidl_status_cb, callback);
-}
-
-Return<void> WifiNanIface::getCapabilitiesRequest(
-    uint16_t cmd_id, getCapabilitiesRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::getCapabilitiesRequestInternal,
-                           hidl_status_cb, cmd_id);
-}
-
-Return<void> WifiNanIface::enableRequest(uint16_t cmd_id,
-                                         const V1_0::NanEnableRequest& msg,
-                                         enableRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::enableRequestInternal, hidl_status_cb,
-                           cmd_id, msg);
-}
-
-Return<void> WifiNanIface::configRequest(uint16_t cmd_id,
-                                         const V1_0::NanConfigRequest& msg,
-                                         configRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::configRequestInternal, hidl_status_cb,
-                           cmd_id, msg);
-}
-
-Return<void> WifiNanIface::disableRequest(uint16_t cmd_id,
-                                          disableRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::disableRequestInternal,
-                           hidl_status_cb, cmd_id);
-}
-
-Return<void> WifiNanIface::startPublishRequest(
-    uint16_t cmd_id, const NanPublishRequest& msg,
-    startPublishRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::startPublishRequestInternal,
-                           hidl_status_cb, cmd_id, msg);
-}
-
-Return<void> WifiNanIface::stopPublishRequest(
-    uint16_t cmd_id, uint8_t sessionId, stopPublishRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::stopPublishRequestInternal,
-                           hidl_status_cb, cmd_id, sessionId);
-}
-
-Return<void> WifiNanIface::startSubscribeRequest(
-    uint16_t cmd_id, const NanSubscribeRequest& msg,
-    startSubscribeRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::startSubscribeRequestInternal,
-                           hidl_status_cb, cmd_id, msg);
-}
-
-Return<void> WifiNanIface::stopSubscribeRequest(
-    uint16_t cmd_id, uint8_t sessionId,
-    stopSubscribeRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::stopSubscribeRequestInternal,
-                           hidl_status_cb, cmd_id, sessionId);
-}
-
-Return<void> WifiNanIface::transmitFollowupRequest(
-    uint16_t cmd_id, const NanTransmitFollowupRequest& msg,
-    transmitFollowupRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::transmitFollowupRequestInternal,
-                           hidl_status_cb, cmd_id, msg);
-}
-
-Return<void> WifiNanIface::createDataInterfaceRequest(
-    uint16_t cmd_id, const hidl_string& iface_name,
-    createDataInterfaceRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::createDataInterfaceRequestInternal,
-                           hidl_status_cb, cmd_id, iface_name);
-}
-
-Return<void> WifiNanIface::deleteDataInterfaceRequest(
-    uint16_t cmd_id, const hidl_string& iface_name,
-    deleteDataInterfaceRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::deleteDataInterfaceRequestInternal,
-                           hidl_status_cb, cmd_id, iface_name);
-}
-
-Return<void> WifiNanIface::initiateDataPathRequest(
-    uint16_t cmd_id, const NanInitiateDataPathRequest& msg,
-    initiateDataPathRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::initiateDataPathRequestInternal,
-                           hidl_status_cb, cmd_id, msg);
-}
-
-Return<void> WifiNanIface::respondToDataPathIndicationRequest(
-    uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg,
-    respondToDataPathIndicationRequest_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-        &WifiNanIface::respondToDataPathIndicationRequestInternal,
-        hidl_status_cb, cmd_id, msg);
-}
-
-Return<void> WifiNanIface::terminateDataPathRequest(
-    uint16_t cmd_id, uint32_t ndpInstanceId,
-    terminateDataPathRequest_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::terminateDataPathRequestInternal,
-                           hidl_status_cb, cmd_id, ndpInstanceId);
-}
-
-Return<void> WifiNanIface::registerEventCallback_1_2(
-    const sp<V1_2::IWifiNanIfaceEventCallback>& callback,
-    registerEventCallback_1_2_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::registerEventCallback_1_2Internal,
-                           hidl_status_cb, callback);
-}
-
-Return<void> WifiNanIface::enableRequest_1_2(
-    uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
-    const V1_2::NanConfigRequestSupplemental& msg2,
-    enableRequest_1_2_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::enableRequest_1_2Internal,
-                           hidl_status_cb, cmd_id, msg1, msg2);
-}
-
-Return<void> WifiNanIface::configRequest_1_2(
-    uint16_t cmd_id, const V1_0::NanConfigRequest& msg1,
-    const V1_2::NanConfigRequestSupplemental& msg2,
-    configRequest_1_2_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::configRequest_1_2Internal,
-                           hidl_status_cb, cmd_id, msg1, msg2);
-}
-
-Return<void> WifiNanIface::enableRequest_1_4(
-    uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
-    const V1_2::NanConfigRequestSupplemental& msg2,
-    enableRequest_1_4_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::enableRequest_1_4Internal,
-                           hidl_status_cb, cmd_id, msg1, msg2);
-}
-
-Return<void> WifiNanIface::configRequest_1_4(
-    uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
-    const V1_2::NanConfigRequestSupplemental& msg2,
-    configRequest_1_4_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::configRequest_1_4Internal,
-                           hidl_status_cb, cmd_id, msg1, msg2);
-}
-
-Return<void> WifiNanIface::registerEventCallback_1_5(
-    const sp<IWifiNanIfaceEventCallback>& callback,
-    registerEventCallback_1_5_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::registerEventCallback_1_5Internal,
-                           hidl_status_cb, callback);
-}
-
-Return<void> WifiNanIface::enableRequest_1_5(
-    uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
-    const NanConfigRequestSupplemental& msg2,
-    enableRequest_1_5_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::enableRequest_1_5Internal,
-                           hidl_status_cb, cmd_id, msg1, msg2);
-}
-
-Return<void> WifiNanIface::configRequest_1_5(
-    uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
-    const NanConfigRequestSupplemental& msg2,
-    configRequest_1_5_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::configRequest_1_5Internal,
-                           hidl_status_cb, cmd_id, msg1, msg2);
-}
-
-Return<void> WifiNanIface::getCapabilitiesRequest_1_5(
-    uint16_t cmd_id, getCapabilitiesRequest_1_5_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiNanIface::getCapabilitiesRequest_1_5Internal,
-                           hidl_status_cb, cmd_id);
-}
-
-std::pair<WifiStatus, std::string> WifiNanIface::getNameInternal() {
-    return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
-}
-
-std::pair<WifiStatus, IfaceType> WifiNanIface::getTypeInternal() {
-    return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::NAN};
-}
-
-WifiStatus WifiNanIface::registerEventCallbackInternal(
-    const sp<V1_0::IWifiNanIfaceEventCallback>& callback) {
-    if (!event_cb_handler_.addCallback(callback)) {
-        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-    }
-    return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t /* cmd_id */) {
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::enableRequestInternal(
-    uint16_t /* cmd_id */, const V1_0::NanEnableRequest& /* msg */) {
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::configRequestInternal(
-    uint16_t /* cmd_id */, const V1_0::NanConfigRequest& /* msg */) {
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::disableRequestInternal(uint16_t cmd_id) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanDisableRequest(ifname_, cmd_id);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::startPublishRequestInternal(
-    uint16_t cmd_id, const NanPublishRequest& msg) {
-    legacy_hal::NanPublishRequest legacy_msg;
-    if (!hidl_struct_util::convertHidlNanPublishRequestToLegacy(msg,
-                                                                &legacy_msg)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanPublishRequest(ifname_, cmd_id, legacy_msg);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::stopPublishRequestInternal(uint16_t cmd_id,
-                                                    uint8_t sessionId) {
-    legacy_hal::NanPublishCancelRequest legacy_msg;
-    legacy_msg.publish_id = sessionId;
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanPublishCancelRequest(ifname_, cmd_id,
-                                                    legacy_msg);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::startSubscribeRequestInternal(
-    uint16_t cmd_id, const NanSubscribeRequest& msg) {
-    legacy_hal::NanSubscribeRequest legacy_msg;
-    if (!hidl_struct_util::convertHidlNanSubscribeRequestToLegacy(
-            msg, &legacy_msg)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanSubscribeRequest(ifname_, cmd_id, legacy_msg);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::stopSubscribeRequestInternal(uint16_t cmd_id,
-                                                      uint8_t sessionId) {
-    legacy_hal::NanSubscribeCancelRequest legacy_msg;
-    legacy_msg.subscribe_id = sessionId;
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanSubscribeCancelRequest(ifname_, cmd_id,
-                                                      legacy_msg);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::transmitFollowupRequestInternal(
-    uint16_t cmd_id, const NanTransmitFollowupRequest& msg) {
-    legacy_hal::NanTransmitFollowupRequest legacy_msg;
-    if (!hidl_struct_util::convertHidlNanTransmitFollowupRequestToLegacy(
-            msg, &legacy_msg)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanTransmitFollowupRequest(ifname_, cmd_id,
-                                                       legacy_msg);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::createDataInterfaceRequestInternal(
-    uint16_t cmd_id, const std::string& iface_name) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanDataInterfaceCreate(ifname_, cmd_id, iface_name);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::deleteDataInterfaceRequestInternal(
-    uint16_t cmd_id, const std::string& iface_name) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, cmd_id, iface_name);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::initiateDataPathRequestInternal(
-    uint16_t cmd_id, const NanInitiateDataPathRequest& msg) {
-    legacy_hal::NanDataPathInitiatorRequest legacy_msg;
-    if (!hidl_struct_util::convertHidlNanDataPathInitiatorRequestToLegacy(
-            msg, &legacy_msg)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanDataRequestInitiator(ifname_, cmd_id,
-                                                    legacy_msg);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::respondToDataPathIndicationRequestInternal(
-    uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg) {
-    legacy_hal::NanDataPathIndicationResponse legacy_msg;
-    if (!hidl_struct_util::convertHidlNanDataPathIndicationResponseToLegacy(
-            msg, &legacy_msg)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanDataIndicationResponse(ifname_, cmd_id,
-                                                      legacy_msg);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::terminateDataPathRequestInternal(
-    uint16_t cmd_id, uint32_t ndpInstanceId) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanDataEnd(ifname_, cmd_id, ndpInstanceId);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::registerEventCallback_1_2Internal(
-    const sp<V1_2::IWifiNanIfaceEventCallback>& callback) {
-    sp<V1_0::IWifiNanIfaceEventCallback> callback_1_0 = callback;
-    if (!event_cb_handler_.addCallback(callback_1_0)) {
-        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-    }
-    if (!event_cb_handler_1_2_.addCallback(callback)) {
-        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-    }
-    return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiNanIface::enableRequest_1_2Internal(
-    uint16_t /* cmd_id */, const V1_0::NanEnableRequest& /* msg1 */,
-    const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::configRequest_1_2Internal(
-    uint16_t /* cmd_id */, const V1_0::NanConfigRequest& /* msg1 */,
-    const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::enableRequest_1_4Internal(
-    uint16_t /* cmd_id */, const V1_4::NanEnableRequest& /* msg1 */,
-    const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::configRequest_1_4Internal(
-    uint16_t /* cmd_id */, const V1_4::NanConfigRequest& /* msg1 */,
-    const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::registerEventCallback_1_5Internal(
-    const sp<IWifiNanIfaceEventCallback>& callback) {
-    sp<V1_0::IWifiNanIfaceEventCallback> callback_1_0 = callback;
-    if (!event_cb_handler_.addCallback(callback_1_0)) {
-        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-    }
-    sp<V1_2::IWifiNanIfaceEventCallback> callback_1_2 = callback;
-    if (!event_cb_handler_1_2_.addCallback(callback_1_2)) {
-        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-    }
-    if (!event_cb_handler_1_5_.addCallback(callback)) {
-        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-    }
-    return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiNanIface::getCapabilitiesRequest_1_5Internal(uint16_t cmd_id) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanGetCapabilities(ifname_, cmd_id);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::enableRequest_1_5Internal(
-    uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
-    const NanConfigRequestSupplemental& msg2) {
-    legacy_hal::NanEnableRequest legacy_msg;
-    if (!hidl_struct_util::convertHidlNanEnableRequest_1_5ToLegacy(
-            msg1, msg2, &legacy_msg)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::configRequest_1_5Internal(
-    uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
-    const NanConfigRequestSupplemental& msg2) {
-    legacy_hal::NanConfigRequest legacy_msg;
-    if (!hidl_struct_util::convertHidlNanConfigRequest_1_5ToLegacy(
-            msg1, msg2, &legacy_msg)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-}  // namespace implementation
-}  // namespace V1_5
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.5/default/wifi_nan_iface.h b/wifi/1.5/default/wifi_nan_iface.h
deleted file mode 100644
index fb9c047..0000000
--- a/wifi/1.5/default/wifi_nan_iface.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_NAN_IFACE_H_
-#define WIFI_NAN_IFACE_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.5/IWifiNanIface.h>
-#include <android/hardware/wifi/1.5/IWifiNanIfaceEventCallback.h>
-
-#include "hidl_callback_util.h"
-#include "wifi_iface_util.h"
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_5 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-using namespace android::hardware::wifi::V1_2;
-
-/**
- * HIDL interface object used to control a NAN Iface instance.
- */
-class WifiNanIface : public V1_5::IWifiNanIface {
-   public:
-    WifiNanIface(const std::string& ifname, bool is_dedicated_iface,
-                 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
-                 const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
-    // Refer to |WifiChip::invalidate()|.
-    void invalidate();
-    bool isValid();
-    std::string getName();
-
-    // HIDL methods exposed.
-    Return<void> getName(getName_cb hidl_status_cb) override;
-    Return<void> getType(getType_cb hidl_status_cb) override;
-    Return<void> registerEventCallback(
-        const sp<V1_0::IWifiNanIfaceEventCallback>& callback,
-        registerEventCallback_cb hidl_status_cb) override;
-    Return<void> getCapabilitiesRequest(
-        uint16_t cmd_id, getCapabilitiesRequest_cb hidl_status_cb) override;
-    Return<void> enableRequest(uint16_t cmd_id,
-                               const V1_0::NanEnableRequest& msg,
-                               enableRequest_cb hidl_status_cb) override;
-    Return<void> configRequest(uint16_t cmd_id,
-                               const V1_0::NanConfigRequest& msg,
-                               configRequest_cb hidl_status_cb) override;
-    Return<void> disableRequest(uint16_t cmd_id,
-                                disableRequest_cb hidl_status_cb) override;
-    Return<void> startPublishRequest(
-        uint16_t cmd_id, const NanPublishRequest& msg,
-        startPublishRequest_cb hidl_status_cb) override;
-    Return<void> stopPublishRequest(
-        uint16_t cmd_id, uint8_t sessionId,
-        stopPublishRequest_cb hidl_status_cb) override;
-    Return<void> startSubscribeRequest(
-        uint16_t cmd_id, const NanSubscribeRequest& msg,
-        startSubscribeRequest_cb hidl_status_cb) override;
-    Return<void> stopSubscribeRequest(
-        uint16_t cmd_id, uint8_t sessionId,
-        stopSubscribeRequest_cb hidl_status_cb) override;
-    Return<void> transmitFollowupRequest(
-        uint16_t cmd_id, const NanTransmitFollowupRequest& msg,
-        transmitFollowupRequest_cb hidl_status_cb) override;
-    Return<void> createDataInterfaceRequest(
-        uint16_t cmd_id, const hidl_string& iface_name,
-        createDataInterfaceRequest_cb hidl_status_cb) override;
-    Return<void> deleteDataInterfaceRequest(
-        uint16_t cmd_id, const hidl_string& iface_name,
-        deleteDataInterfaceRequest_cb hidl_status_cb) override;
-    Return<void> initiateDataPathRequest(
-        uint16_t cmd_id, const NanInitiateDataPathRequest& msg,
-        initiateDataPathRequest_cb hidl_status_cb) override;
-    Return<void> respondToDataPathIndicationRequest(
-        uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg,
-        respondToDataPathIndicationRequest_cb hidl_status_cb) override;
-    Return<void> terminateDataPathRequest(
-        uint16_t cmd_id, uint32_t ndpInstanceId,
-        terminateDataPathRequest_cb hidl_status_cb) override;
-
-    Return<void> registerEventCallback_1_2(
-        const sp<V1_2::IWifiNanIfaceEventCallback>& callback,
-        registerEventCallback_1_2_cb hidl_status_cb) override;
-    Return<void> enableRequest_1_2(
-        uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
-        const V1_2::NanConfigRequestSupplemental& msg2,
-        enableRequest_1_2_cb hidl_status_cb) override;
-    Return<void> configRequest_1_2(
-        uint16_t cmd_id, const V1_0::NanConfigRequest& msg1,
-        const V1_2::NanConfigRequestSupplemental& msg2,
-        configRequest_1_2_cb hidl_status_cb) override;
-    Return<void> enableRequest_1_4(
-        uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
-        const V1_2::NanConfigRequestSupplemental& msg2,
-        enableRequest_1_4_cb hidl_status_cb) override;
-    Return<void> configRequest_1_4(
-        uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
-        const V1_2::NanConfigRequestSupplemental& msg2,
-        configRequest_1_4_cb hidl_status_cb) override;
-    Return<void> registerEventCallback_1_5(
-        const sp<IWifiNanIfaceEventCallback>& callback,
-        registerEventCallback_1_5_cb hidl_status_cb) override;
-    Return<void> enableRequest_1_5(
-        uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
-        const NanConfigRequestSupplemental& msg2,
-        enableRequest_1_4_cb hidl_status_cb) override;
-    Return<void> configRequest_1_5(
-        uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
-        const NanConfigRequestSupplemental& msg2,
-        configRequest_1_4_cb hidl_status_cb) override;
-    Return<void> getCapabilitiesRequest_1_5(
-        uint16_t cmd_id, getCapabilitiesRequest_cb hidl_status_cb) override;
-
-   private:
-    // Corresponding worker functions for the HIDL methods.
-    std::pair<WifiStatus, std::string> getNameInternal();
-    std::pair<WifiStatus, IfaceType> getTypeInternal();
-    WifiStatus registerEventCallbackInternal(
-        const sp<V1_0::IWifiNanIfaceEventCallback>& callback);
-    WifiStatus getCapabilitiesRequestInternal(uint16_t cmd_id);
-    WifiStatus enableRequestInternal(uint16_t cmd_id,
-                                     const V1_0::NanEnableRequest& msg);
-    WifiStatus configRequestInternal(uint16_t cmd_id,
-                                     const V1_0::NanConfigRequest& msg);
-    WifiStatus disableRequestInternal(uint16_t cmd_id);
-    WifiStatus startPublishRequestInternal(uint16_t cmd_id,
-                                           const NanPublishRequest& msg);
-    WifiStatus stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId);
-    WifiStatus startSubscribeRequestInternal(uint16_t cmd_id,
-                                             const NanSubscribeRequest& msg);
-    WifiStatus stopSubscribeRequestInternal(uint16_t cmd_id, uint8_t sessionId);
-    WifiStatus transmitFollowupRequestInternal(
-        uint16_t cmd_id, const NanTransmitFollowupRequest& msg);
-    WifiStatus createDataInterfaceRequestInternal(
-        uint16_t cmd_id, const std::string& iface_name);
-    WifiStatus deleteDataInterfaceRequestInternal(
-        uint16_t cmd_id, const std::string& iface_name);
-    WifiStatus initiateDataPathRequestInternal(
-        uint16_t cmd_id, const NanInitiateDataPathRequest& msg);
-    WifiStatus respondToDataPathIndicationRequestInternal(
-        uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg);
-    WifiStatus terminateDataPathRequestInternal(uint16_t cmd_id,
-                                                uint32_t ndpInstanceId);
-
-    WifiStatus registerEventCallback_1_2Internal(
-        const sp<V1_2::IWifiNanIfaceEventCallback>& callback);
-    WifiStatus enableRequest_1_2Internal(
-        uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
-        const V1_2::NanConfigRequestSupplemental& msg2);
-    WifiStatus configRequest_1_2Internal(
-        uint16_t cmd_id, const V1_0::NanConfigRequest& msg,
-        const V1_2::NanConfigRequestSupplemental& msg2);
-    WifiStatus enableRequest_1_4Internal(
-        uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
-        const V1_2::NanConfigRequestSupplemental& msg2);
-    WifiStatus configRequest_1_4Internal(
-        uint16_t cmd_id, const V1_4::NanConfigRequest& msg,
-        const V1_2::NanConfigRequestSupplemental& msg2);
-    WifiStatus registerEventCallback_1_5Internal(
-        const sp<IWifiNanIfaceEventCallback>& callback);
-    WifiStatus enableRequest_1_5Internal(
-        uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
-        const NanConfigRequestSupplemental& msg2);
-    WifiStatus configRequest_1_5Internal(
-        uint16_t cmd_id, const V1_4::NanConfigRequest& msg,
-        const NanConfigRequestSupplemental& msg2);
-    WifiStatus getCapabilitiesRequest_1_5Internal(uint16_t cmd_id);
-
-    // all 1_0 and descendant callbacks
-    std::set<sp<V1_0::IWifiNanIfaceEventCallback>> getEventCallbacks();
-    // all 1_2 and descendant callbacks
-    std::set<sp<V1_2::IWifiNanIfaceEventCallback>> getEventCallbacks_1_2();
-    // all 1_5 and descendant callbacks
-    std::set<sp<IWifiNanIfaceEventCallback>> getEventCallbacks_1_5();
-
-    std::string ifname_;
-    bool is_dedicated_iface_;
-    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-    std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
-    bool is_valid_;
-    hidl_callback_util::HidlCallbackHandler<V1_0::IWifiNanIfaceEventCallback>
-        event_cb_handler_;
-    hidl_callback_util::HidlCallbackHandler<V1_2::IWifiNanIfaceEventCallback>
-        event_cb_handler_1_2_;
-    hidl_callback_util::HidlCallbackHandler<IWifiNanIfaceEventCallback>
-        event_cb_handler_1_5_;
-
-    DISALLOW_COPY_AND_ASSIGN(WifiNanIface);
-};
-
-}  // namespace implementation
-}  // namespace V1_5
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_NAN_IFACE_H_
diff --git a/wifi/1.5/default/wifi_rtt_controller.cpp b/wifi/1.5/default/wifi_rtt_controller.cpp
deleted file mode 100644
index a0f9969..0000000
--- a/wifi/1.5/default/wifi_rtt_controller.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_rtt_controller.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_5 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiRttController::WifiRttController(
-    const std::string& iface_name, const sp<IWifiIface>& bound_iface,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
-    : ifname_(iface_name),
-      bound_iface_(bound_iface),
-      legacy_hal_(legacy_hal),
-      is_valid_(true) {}
-
-void WifiRttController::invalidate() {
-    legacy_hal_.reset();
-    event_callbacks_.clear();
-    is_valid_ = false;
-}
-
-bool WifiRttController::isValid() { return is_valid_; }
-
-std::vector<sp<V1_4::IWifiRttControllerEventCallback>>
-WifiRttController::getEventCallbacks() {
-    return event_callbacks_;
-}
-
-std::string WifiRttController::getIfaceName() { return ifname_; }
-
-Return<void> WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::getBoundIfaceInternal, hidl_status_cb);
-}
-
-Return<void> WifiRttController::registerEventCallback(
-    const sp<V1_0::IWifiRttControllerEventCallback>& callback,
-    registerEventCallback_cb hidl_status_cb) {
-    return validateAndCall(this,
-                           WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                           &WifiRttController::registerEventCallbackInternal,
-                           hidl_status_cb, callback);
-}
-
-Return<void> WifiRttController::rangeRequest(
-    uint32_t cmd_id, const hidl_vec<V1_0::RttConfig>& rtt_configs,
-    rangeRequest_cb hidl_status_cb) {
-    return validateAndCall(this,
-                           WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                           &WifiRttController::rangeRequestInternal,
-                           hidl_status_cb, cmd_id, rtt_configs);
-}
-
-Return<void> WifiRttController::rangeCancel(
-    uint32_t cmd_id, const hidl_vec<hidl_array<uint8_t, 6>>& addrs,
-    rangeCancel_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::rangeCancelInternal, hidl_status_cb, cmd_id, addrs);
-}
-
-Return<void> WifiRttController::getCapabilities(
-    getCapabilities_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::getCapabilitiesInternal, hidl_status_cb);
-}
-
-Return<void> WifiRttController::setLci(uint32_t cmd_id,
-                                       const RttLciInformation& lci,
-                                       setLci_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::setLciInternal, hidl_status_cb, cmd_id, lci);
-}
-
-Return<void> WifiRttController::setLcr(uint32_t cmd_id,
-                                       const RttLcrInformation& lcr,
-                                       setLcr_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::setLcrInternal, hidl_status_cb, cmd_id, lcr);
-}
-
-Return<void> WifiRttController::getResponderInfo(
-    getResponderInfo_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::getResponderInfoInternal, hidl_status_cb);
-}
-
-Return<void> WifiRttController::enableResponder(
-    uint32_t cmd_id, const WifiChannelInfo& channel_hint,
-    uint32_t max_duration_seconds, const V1_0::RttResponder& info,
-    enableResponder_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::enableResponderInternal, hidl_status_cb, cmd_id,
-        channel_hint, max_duration_seconds, info);
-}
-
-Return<void> WifiRttController::disableResponder(
-    uint32_t cmd_id, disableResponder_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::disableResponderInternal, hidl_status_cb, cmd_id);
-}
-
-Return<void> WifiRttController::registerEventCallback_1_4(
-    const sp<V1_4::IWifiRttControllerEventCallback>& callback,
-    registerEventCallback_1_4_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::registerEventCallbackInternal_1_4, hidl_status_cb,
-        callback);
-}
-
-Return<void> WifiRttController::rangeRequest_1_4(
-    uint32_t cmd_id, const hidl_vec<V1_4::RttConfig>& rtt_configs,
-    rangeRequest_1_4_cb hidl_status_cb) {
-    return validateAndCall(this,
-                           WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                           &WifiRttController::rangeRequestInternal_1_4,
-                           hidl_status_cb, cmd_id, rtt_configs);
-}
-
-Return<void> WifiRttController::getCapabilities_1_4(
-    getCapabilities_1_4_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::getCapabilitiesInternal_1_4, hidl_status_cb);
-}
-
-Return<void> WifiRttController::getResponderInfo_1_4(
-    getResponderInfo_1_4_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::getResponderInfoInternal_1_4, hidl_status_cb);
-}
-
-Return<void> WifiRttController::enableResponder_1_4(
-    uint32_t cmd_id, const WifiChannelInfo& channel_hint,
-    uint32_t max_duration_seconds, const V1_4::RttResponder& info,
-    enableResponder_1_4_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-        &WifiRttController::enableResponderInternal_1_4, hidl_status_cb, cmd_id,
-        channel_hint, max_duration_seconds, info);
-}
-
-std::pair<WifiStatus, sp<IWifiIface>>
-WifiRttController::getBoundIfaceInternal() {
-    return {createWifiStatus(WifiStatusCode::SUCCESS), bound_iface_};
-}
-
-WifiStatus WifiRttController::registerEventCallbackInternal(
-    const sp<V1_0::IWifiRttControllerEventCallback>& /* callback */) {
-    // Deprecated support for this api
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiRttController::rangeRequestInternal(
-    uint32_t /* cmd_id */,
-    const std::vector<V1_0::RttConfig>& /* rtt_configs */) {
-    // Deprecated support for this api
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiRttController::rangeCancelInternal(
-    uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs) {
-    std::vector<std::array<uint8_t, 6>> legacy_addrs;
-    for (const auto& addr : addrs) {
-        legacy_addrs.push_back(addr);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->cancelRttRangeRequest(ifname_, cmd_id,
-                                                  legacy_addrs);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, V1_0::RttCapabilities>
-WifiRttController::getCapabilitiesInternal() {
-    // Deprecated support for this api
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-WifiStatus WifiRttController::setLciInternal(uint32_t cmd_id,
-                                             const RttLciInformation& lci) {
-    legacy_hal::wifi_lci_information legacy_lci;
-    if (!hidl_struct_util::convertHidlRttLciInformationToLegacy(lci,
-                                                                &legacy_lci)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->setRttLci(ifname_, cmd_id, legacy_lci);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiRttController::setLcrInternal(uint32_t cmd_id,
-                                             const RttLcrInformation& lcr) {
-    legacy_hal::wifi_lcr_information legacy_lcr;
-    if (!hidl_struct_util::convertHidlRttLcrInformationToLegacy(lcr,
-                                                                &legacy_lcr)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->setRttLcr(ifname_, cmd_id, legacy_lcr);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, V1_0::RttResponder>
-WifiRttController::getResponderInfoInternal() {
-    // Deprecated support for this api
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-WifiStatus WifiRttController::enableResponderInternal(
-    uint32_t /* cmd_id */, const WifiChannelInfo& /* channel_hint */,
-    uint32_t /* max_duration_seconds */, const V1_0::RttResponder& /* info */) {
-    // Deprecated support for this api
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED)};
-}
-
-WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->disableRttResponder(ifname_, cmd_id);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiRttController::registerEventCallbackInternal_1_4(
-    const sp<V1_4::IWifiRttControllerEventCallback>& callback) {
-    // TODO(b/31632518): remove the callback when the client is destroyed
-    event_callbacks_.emplace_back(callback);
-    return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiRttController::rangeRequestInternal_1_4(
-    uint32_t cmd_id, const std::vector<V1_4::RttConfig>& rtt_configs) {
-    std::vector<legacy_hal::wifi_rtt_config> legacy_configs;
-    if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy(
-            rtt_configs, &legacy_configs)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    android::wp<WifiRttController> weak_ptr_this(this);
-    const auto& on_results_callback =
-        [weak_ptr_this](
-            legacy_hal::wifi_request_id id,
-            const std::vector<const legacy_hal::wifi_rtt_result*>& results) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            std::vector<V1_4::RttResult> hidl_results;
-            if (!hidl_struct_util::convertLegacyVectorOfRttResultToHidl(
-                    results, &hidl_results)) {
-                LOG(ERROR) << "Failed to convert rtt results to HIDL structs";
-                return;
-            }
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                callback->onResults_1_4(id, hidl_results);
-            }
-        };
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->startRttRangeRequest(
-            ifname_, cmd_id, legacy_configs, on_results_callback);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, V1_4::RttCapabilities>
-WifiRttController::getCapabilitiesInternal_1_4() {
-    legacy_hal::wifi_error legacy_status;
-    legacy_hal::wifi_rtt_capabilities legacy_caps;
-    std::tie(legacy_status, legacy_caps) =
-        legacy_hal_.lock()->getRttCapabilities(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), {}};
-    }
-    V1_4::RttCapabilities hidl_caps;
-    if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps,
-                                                              &hidl_caps)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-std::pair<WifiStatus, V1_4::RttResponder>
-WifiRttController::getResponderInfoInternal_1_4() {
-    legacy_hal::wifi_error legacy_status;
-    legacy_hal::wifi_rtt_responder legacy_responder;
-    std::tie(legacy_status, legacy_responder) =
-        legacy_hal_.lock()->getRttResponderInfo(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), {}};
-    }
-    V1_4::RttResponder hidl_responder;
-    if (!hidl_struct_util::convertLegacyRttResponderToHidl(legacy_responder,
-                                                           &hidl_responder)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_responder};
-}
-
-WifiStatus WifiRttController::enableResponderInternal_1_4(
-    uint32_t cmd_id, const WifiChannelInfo& channel_hint,
-    uint32_t max_duration_seconds, const V1_4::RttResponder& info) {
-    legacy_hal::wifi_channel_info legacy_channel_info;
-    if (!hidl_struct_util::convertHidlWifiChannelInfoToLegacy(
-            channel_hint, &legacy_channel_info)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_rtt_responder legacy_responder;
-    if (!hidl_struct_util::convertHidlRttResponderToLegacy(info,
-                                                           &legacy_responder)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->enableRttResponder(
-            ifname_, cmd_id, legacy_channel_info, max_duration_seconds,
-            legacy_responder);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-}  // namespace implementation
-}  // namespace V1_5
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.5/default/wifi_rtt_controller.h b/wifi/1.5/default/wifi_rtt_controller.h
deleted file mode 100644
index 9ac3e06..0000000
--- a/wifi/1.5/default/wifi_rtt_controller.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_RTT_CONTROLLER_H_
-#define WIFI_RTT_CONTROLLER_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiIface.h>
-#include <android/hardware/wifi/1.4/IWifiRttController.h>
-#include <android/hardware/wifi/1.4/IWifiRttControllerEventCallback.h>
-
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_5 {
-namespace implementation {
-
-/**
- * HIDL interface object used to control all RTT operations.
- */
-class WifiRttController : public V1_4::IWifiRttController {
-   public:
-    WifiRttController(
-        const std::string& iface_name, const sp<IWifiIface>& bound_iface,
-        const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
-    // Refer to |WifiChip::invalidate()|.
-    void invalidate();
-    bool isValid();
-    std::vector<sp<V1_4::IWifiRttControllerEventCallback>> getEventCallbacks();
-    std::string getIfaceName();
-
-    // HIDL methods exposed.
-    Return<void> getBoundIface(getBoundIface_cb hidl_status_cb) override;
-    Return<void> registerEventCallback(
-        const sp<V1_0::IWifiRttControllerEventCallback>& callback,
-        registerEventCallback_cb hidl_status_cb) override;
-    Return<void> rangeRequest(uint32_t cmd_id,
-                              const hidl_vec<V1_0::RttConfig>& rtt_configs,
-                              rangeRequest_cb hidl_status_cb) override;
-    Return<void> rangeCancel(uint32_t cmd_id,
-                             const hidl_vec<hidl_array<uint8_t, 6>>& addrs,
-                             rangeCancel_cb hidl_status_cb) override;
-    Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
-    Return<void> setLci(uint32_t cmd_id, const RttLciInformation& lci,
-                        setLci_cb hidl_status_cb) override;
-    Return<void> setLcr(uint32_t cmd_id, const RttLcrInformation& lcr,
-                        setLcr_cb hidl_status_cb) override;
-    Return<void> getResponderInfo(getResponderInfo_cb hidl_status_cb) override;
-    Return<void> enableResponder(uint32_t cmd_id,
-                                 const WifiChannelInfo& channel_hint,
-                                 uint32_t max_duration_seconds,
-                                 const V1_0::RttResponder& info,
-                                 enableResponder_cb hidl_status_cb) override;
-    Return<void> disableResponder(uint32_t cmd_id,
-                                  disableResponder_cb hidl_status_cb) override;
-    Return<void> registerEventCallback_1_4(
-        const sp<V1_4::IWifiRttControllerEventCallback>& callback,
-        registerEventCallback_1_4_cb hidl_status_cb) override;
-    Return<void> rangeRequest_1_4(uint32_t cmd_id,
-                                  const hidl_vec<V1_4::RttConfig>& rtt_configs,
-                                  rangeRequest_1_4_cb hidl_status_cb) override;
-    Return<void> getCapabilities_1_4(
-        getCapabilities_1_4_cb hidl_status_cb) override;
-    Return<void> getResponderInfo_1_4(
-        getResponderInfo_1_4_cb hidl_status_cb) override;
-    Return<void> enableResponder_1_4(
-        uint32_t cmd_id, const WifiChannelInfo& channel_hint,
-        uint32_t max_duration_seconds, const V1_4::RttResponder& info,
-        enableResponder_1_4_cb hidl_status_cb) override;
-
-   private:
-    // Corresponding worker functions for the HIDL methods.
-    std::pair<WifiStatus, sp<IWifiIface>> getBoundIfaceInternal();
-    WifiStatus registerEventCallbackInternal(
-        const sp<V1_0::IWifiRttControllerEventCallback>& callback);
-    WifiStatus rangeRequestInternal(
-        uint32_t cmd_id, const std::vector<V1_0::RttConfig>& rtt_configs);
-    WifiStatus rangeCancelInternal(
-        uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs);
-    std::pair<WifiStatus, V1_0::RttCapabilities> getCapabilitiesInternal();
-    WifiStatus setLciInternal(uint32_t cmd_id, const RttLciInformation& lci);
-    WifiStatus setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr);
-    std::pair<WifiStatus, V1_0::RttResponder> getResponderInfoInternal();
-    WifiStatus enableResponderInternal(uint32_t cmd_id,
-                                       const WifiChannelInfo& channel_hint,
-                                       uint32_t max_duration_seconds,
-                                       const V1_0::RttResponder& info);
-    WifiStatus disableResponderInternal(uint32_t cmd_id);
-    WifiStatus registerEventCallbackInternal_1_4(
-        const sp<V1_4::IWifiRttControllerEventCallback>& callback);
-    WifiStatus rangeRequestInternal_1_4(
-        uint32_t cmd_id, const std::vector<V1_4::RttConfig>& rtt_configs);
-    std::pair<WifiStatus, V1_4::RttCapabilities> getCapabilitiesInternal_1_4();
-    std::pair<WifiStatus, V1_4::RttResponder> getResponderInfoInternal_1_4();
-    WifiStatus enableResponderInternal_1_4(uint32_t cmd_id,
-                                           const WifiChannelInfo& channel_hint,
-                                           uint32_t max_duration_seconds,
-                                           const V1_4::RttResponder& info);
-
-    std::string ifname_;
-    sp<IWifiIface> bound_iface_;
-    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-    std::vector<sp<V1_4::IWifiRttControllerEventCallback>> event_callbacks_;
-    bool is_valid_;
-
-    DISALLOW_COPY_AND_ASSIGN(WifiRttController);
-};
-
-}  // namespace implementation
-}  // namespace V1_5
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_RTT_CONTROLLER_H_
diff --git a/wifi/1.5/default/wifi_sta_iface.cpp b/wifi/1.5/default/wifi_sta_iface.cpp
deleted file mode 100644
index 92c9fe4..0000000
--- a/wifi/1.5/default/wifi_sta_iface.cpp
+++ /dev/null
@@ -1,675 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_sta_iface.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_5 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiStaIface::WifiStaIface(
-    const std::string& ifname,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
-    const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
-    : ifname_(ifname),
-      legacy_hal_(legacy_hal),
-      iface_util_(iface_util),
-      is_valid_(true) {
-    // Turn on DFS channel usage for STA iface.
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->setDfsFlag(ifname_, true);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR)
-            << "Failed to set DFS flag; DFS channels may be unavailable.";
-    }
-}
-
-void WifiStaIface::invalidate() {
-    legacy_hal_.reset();
-    event_cb_handler_.invalidate();
-    is_valid_ = false;
-}
-
-bool WifiStaIface::isValid() { return is_valid_; }
-
-std::string WifiStaIface::getName() { return ifname_; }
-
-std::set<sp<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() {
-    return event_cb_handler_.getCallbacks();
-}
-
-Return<void> WifiStaIface::getName(getName_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getNameInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getType(getType_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getTypeInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::registerEventCallback(
-    const sp<IWifiStaIfaceEventCallback>& callback,
-    registerEventCallback_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::registerEventCallbackInternal,
-                           hidl_status_cb, callback);
-}
-
-Return<void> WifiStaIface::getCapabilities(getCapabilities_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getCapabilitiesInternal,
-                           hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getApfPacketFilterCapabilities(
-    getApfPacketFilterCapabilities_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-        &WifiStaIface::getApfPacketFilterCapabilitiesInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::installApfPacketFilter(
-    uint32_t cmd_id, const hidl_vec<uint8_t>& program,
-    installApfPacketFilter_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::installApfPacketFilterInternal,
-                           hidl_status_cb, cmd_id, program);
-}
-
-Return<void> WifiStaIface::readApfPacketFilterData(
-    readApfPacketFilterData_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::readApfPacketFilterDataInternal,
-                           hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getBackgroundScanCapabilities(
-    getBackgroundScanCapabilities_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getBackgroundScanCapabilitiesInternal,
-                           hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getValidFrequenciesForBand(
-    V1_0::WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getValidFrequenciesForBandInternal,
-                           hidl_status_cb, band);
-}
-
-Return<void> WifiStaIface::startBackgroundScan(
-    uint32_t cmd_id, const StaBackgroundScanParameters& params,
-    startBackgroundScan_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::startBackgroundScanInternal,
-                           hidl_status_cb, cmd_id, params);
-}
-
-Return<void> WifiStaIface::stopBackgroundScan(
-    uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::stopBackgroundScanInternal,
-                           hidl_status_cb, cmd_id);
-}
-
-Return<void> WifiStaIface::enableLinkLayerStatsCollection(
-    bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-        &WifiStaIface::enableLinkLayerStatsCollectionInternal, hidl_status_cb,
-        debug);
-}
-
-Return<void> WifiStaIface::disableLinkLayerStatsCollection(
-    disableLinkLayerStatsCollection_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-        &WifiStaIface::disableLinkLayerStatsCollectionInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getLinkLayerStats(
-    getLinkLayerStats_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getLinkLayerStatsInternal,
-                           hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getLinkLayerStats_1_3(
-    getLinkLayerStats_1_3_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getLinkLayerStatsInternal_1_3,
-                           hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getLinkLayerStats_1_5(
-    getLinkLayerStats_1_5_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getLinkLayerStatsInternal_1_5,
-                           hidl_status_cb);
-}
-
-Return<void> WifiStaIface::startRssiMonitoring(
-    uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
-    startRssiMonitoring_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::startRssiMonitoringInternal,
-                           hidl_status_cb, cmd_id, max_rssi, min_rssi);
-}
-
-Return<void> WifiStaIface::stopRssiMonitoring(
-    uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::stopRssiMonitoringInternal,
-                           hidl_status_cb, cmd_id);
-}
-
-Return<void> WifiStaIface::getRoamingCapabilities(
-    getRoamingCapabilities_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getRoamingCapabilitiesInternal,
-                           hidl_status_cb);
-}
-
-Return<void> WifiStaIface::configureRoaming(
-    const StaRoamingConfig& config, configureRoaming_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::configureRoamingInternal,
-                           hidl_status_cb, config);
-}
-
-Return<void> WifiStaIface::setRoamingState(StaRoamingState state,
-                                           setRoamingState_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::setRoamingStateInternal,
-                           hidl_status_cb, state);
-}
-
-Return<void> WifiStaIface::enableNdOffload(bool enable,
-                                           enableNdOffload_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::enableNdOffloadInternal,
-                           hidl_status_cb, enable);
-}
-
-Return<void> WifiStaIface::startSendingKeepAlivePackets(
-    uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data,
-    uint16_t ether_type, const hidl_array<uint8_t, 6>& src_address,
-    const hidl_array<uint8_t, 6>& dst_address, uint32_t period_in_ms,
-    startSendingKeepAlivePackets_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::startSendingKeepAlivePacketsInternal,
-                           hidl_status_cb, cmd_id, ip_packet_data, ether_type,
-                           src_address, dst_address, period_in_ms);
-}
-
-Return<void> WifiStaIface::stopSendingKeepAlivePackets(
-    uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::stopSendingKeepAlivePacketsInternal,
-                           hidl_status_cb, cmd_id);
-}
-
-Return<void> WifiStaIface::setScanningMacOui(
-    const hidl_array<uint8_t, 3>& oui, setScanningMacOui_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::setScanningMacOuiInternal,
-                           hidl_status_cb, oui);
-}
-
-Return<void> WifiStaIface::startDebugPacketFateMonitoring(
-    startDebugPacketFateMonitoring_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-        &WifiStaIface::startDebugPacketFateMonitoringInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getDebugTxPacketFates(
-    getDebugTxPacketFates_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getDebugTxPacketFatesInternal,
-                           hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getDebugRxPacketFates(
-    getDebugRxPacketFates_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getDebugRxPacketFatesInternal,
-                           hidl_status_cb);
-}
-
-Return<void> WifiStaIface::setMacAddress(const hidl_array<uint8_t, 6>& mac,
-                                         setMacAddress_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::setMacAddressInternal, hidl_status_cb,
-                           mac);
-}
-
-Return<void> WifiStaIface::getFactoryMacAddress(
-    getFactoryMacAddress_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getFactoryMacAddressInternal,
-                           hidl_status_cb);
-}
-
-Return<void> WifiStaIface::setScanMode(bool enable,
-                                       setScanMode_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::setScanModeInternal, hidl_status_cb,
-                           enable);
-}
-
-std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() {
-    return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
-}
-
-std::pair<WifiStatus, IfaceType> WifiStaIface::getTypeInternal() {
-    return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::STA};
-}
-
-WifiStatus WifiStaIface::registerEventCallbackInternal(
-    const sp<IWifiStaIfaceEventCallback>& callback) {
-    if (!event_cb_handler_.addCallback(callback)) {
-        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-    }
-    return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() {
-    legacy_hal::wifi_error legacy_status;
-    uint64_t legacy_feature_set;
-    std::tie(legacy_status, legacy_feature_set) =
-        legacy_hal_.lock()->getSupportedFeatureSet(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), 0};
-    }
-    uint32_t legacy_logger_feature_set;
-    std::tie(legacy_status, legacy_logger_feature_set) =
-        legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        // some devices don't support querying logger feature set
-        legacy_logger_feature_set = 0;
-    }
-    uint32_t hidl_caps;
-    if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities(
-            legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-std::pair<WifiStatus, StaApfPacketFilterCapabilities>
-WifiStaIface::getApfPacketFilterCapabilitiesInternal() {
-    legacy_hal::wifi_error legacy_status;
-    legacy_hal::PacketFilterCapabilities legacy_caps;
-    std::tie(legacy_status, legacy_caps) =
-        legacy_hal_.lock()->getPacketFilterCapabilities(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), {}};
-    }
-    StaApfPacketFilterCapabilities hidl_caps;
-    if (!hidl_struct_util::convertLegacyApfCapabilitiesToHidl(legacy_caps,
-                                                              &hidl_caps)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-WifiStatus WifiStaIface::installApfPacketFilterInternal(
-    uint32_t /* cmd_id */, const std::vector<uint8_t>& program) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->setPacketFilter(ifname_, program);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, std::vector<uint8_t>>
-WifiStaIface::readApfPacketFilterDataInternal() {
-    const std::pair<legacy_hal::wifi_error, std::vector<uint8_t>>
-        legacy_status_and_data =
-            legacy_hal_.lock()->readApfPacketFilterData(ifname_);
-    return {createWifiStatusFromLegacyError(legacy_status_and_data.first),
-            std::move(legacy_status_and_data.second)};
-}
-
-std::pair<WifiStatus, StaBackgroundScanCapabilities>
-WifiStaIface::getBackgroundScanCapabilitiesInternal() {
-    legacy_hal::wifi_error legacy_status;
-    legacy_hal::wifi_gscan_capabilities legacy_caps;
-    std::tie(legacy_status, legacy_caps) =
-        legacy_hal_.lock()->getGscanCapabilities(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), {}};
-    }
-    StaBackgroundScanCapabilities hidl_caps;
-    if (!hidl_struct_util::convertLegacyGscanCapabilitiesToHidl(legacy_caps,
-                                                                &hidl_caps)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-WifiStaIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) {
-    static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t),
-                  "Size mismatch");
-    legacy_hal::wifi_error legacy_status;
-    std::vector<uint32_t> valid_frequencies;
-    std::tie(legacy_status, valid_frequencies) =
-        legacy_hal_.lock()->getValidFrequenciesForBand(
-            ifname_, hidl_struct_util::convertHidlWifiBandToLegacy(band));
-    return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
-}
-
-WifiStatus WifiStaIface::startBackgroundScanInternal(
-    uint32_t cmd_id, const StaBackgroundScanParameters& params) {
-    legacy_hal::wifi_scan_cmd_params legacy_params;
-    if (!hidl_struct_util::convertHidlGscanParamsToLegacy(params,
-                                                          &legacy_params)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    android::wp<WifiStaIface> weak_ptr_this(this);
-    const auto& on_failure_callback =
-        [weak_ptr_this](legacy_hal::wifi_request_id id) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->onBackgroundScanFailure(id).isOk()) {
-                    LOG(ERROR)
-                        << "Failed to invoke onBackgroundScanFailure callback";
-                }
-            }
-        };
-    const auto& on_results_callback =
-        [weak_ptr_this](
-            legacy_hal::wifi_request_id id,
-            const std::vector<legacy_hal::wifi_cached_scan_results>& results) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            std::vector<StaScanData> hidl_scan_datas;
-            if (!hidl_struct_util::
-                    convertLegacyVectorOfCachedGscanResultsToHidl(
-                        results, &hidl_scan_datas)) {
-                LOG(ERROR) << "Failed to convert scan results to HIDL structs";
-                return;
-            }
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->onBackgroundScanResults(id, hidl_scan_datas)
-                         .isOk()) {
-                    LOG(ERROR)
-                        << "Failed to invoke onBackgroundScanResults callback";
-                }
-            }
-        };
-    const auto& on_full_result_callback = [weak_ptr_this](
-                                              legacy_hal::wifi_request_id id,
-                                              const legacy_hal::
-                                                  wifi_scan_result* result,
-                                              uint32_t buckets_scanned) {
-        const auto shared_ptr_this = weak_ptr_this.promote();
-        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-            LOG(ERROR) << "Callback invoked on an invalid object";
-            return;
-        }
-        StaScanResult hidl_scan_result;
-        if (!hidl_struct_util::convertLegacyGscanResultToHidl(
-                *result, true, &hidl_scan_result)) {
-            LOG(ERROR) << "Failed to convert full scan results to HIDL structs";
-            return;
-        }
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-            if (!callback
-                     ->onBackgroundFullScanResult(id, buckets_scanned,
-                                                  hidl_scan_result)
-                     .isOk()) {
-                LOG(ERROR)
-                    << "Failed to invoke onBackgroundFullScanResult callback";
-            }
-        }
-    };
-    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startGscan(
-        ifname_, cmd_id, legacy_params, on_failure_callback,
-        on_results_callback, on_full_result_callback);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::stopBackgroundScanInternal(uint32_t cmd_id) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->stopGscan(ifname_, cmd_id);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->enableLinkLayerStats(ifname_, debug);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->disableLinkLayerStats(ifname_);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, V1_0::StaLinkLayerStats>
-WifiStaIface::getLinkLayerStatsInternal() {
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-std::pair<WifiStatus, V1_3::StaLinkLayerStats>
-WifiStaIface::getLinkLayerStatsInternal_1_3() {
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-std::pair<WifiStatus, V1_5::StaLinkLayerStats>
-WifiStaIface::getLinkLayerStatsInternal_1_5() {
-    legacy_hal::wifi_error legacy_status;
-    legacy_hal::LinkLayerStats legacy_stats;
-    std::tie(legacy_status, legacy_stats) =
-        legacy_hal_.lock()->getLinkLayerStats(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), {}};
-    }
-    V1_5::StaLinkLayerStats hidl_stats;
-    if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
-                                                             &hidl_stats)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
-}
-
-WifiStatus WifiStaIface::startRssiMonitoringInternal(uint32_t cmd_id,
-                                                     int32_t max_rssi,
-                                                     int32_t min_rssi) {
-    android::wp<WifiStaIface> weak_ptr_this(this);
-    const auto& on_threshold_breached_callback =
-        [weak_ptr_this](legacy_hal::wifi_request_id id,
-                        std::array<uint8_t, 6> bssid, int8_t rssi) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->onRssiThresholdBreached(id, bssid, rssi)
-                         .isOk()) {
-                    LOG(ERROR)
-                        << "Failed to invoke onRssiThresholdBreached callback";
-                }
-            }
-        };
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->startRssiMonitoring(ifname_, cmd_id, max_rssi,
-                                                min_rssi,
-                                                on_threshold_breached_callback);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::stopRssiMonitoringInternal(uint32_t cmd_id) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->stopRssiMonitoring(ifname_, cmd_id);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, StaRoamingCapabilities>
-WifiStaIface::getRoamingCapabilitiesInternal() {
-    legacy_hal::wifi_error legacy_status;
-    legacy_hal::wifi_roaming_capabilities legacy_caps;
-    std::tie(legacy_status, legacy_caps) =
-        legacy_hal_.lock()->getRoamingCapabilities(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), {}};
-    }
-    StaRoamingCapabilities hidl_caps;
-    if (!hidl_struct_util::convertLegacyRoamingCapabilitiesToHidl(legacy_caps,
-                                                                  &hidl_caps)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-WifiStatus WifiStaIface::configureRoamingInternal(
-    const StaRoamingConfig& config) {
-    legacy_hal::wifi_roaming_config legacy_config;
-    if (!hidl_struct_util::convertHidlRoamingConfigToLegacy(config,
-                                                            &legacy_config)) {
-        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-    }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->configureRoaming(ifname_, legacy_config);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::setRoamingStateInternal(StaRoamingState state) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->enableFirmwareRoaming(
-            ifname_, hidl_struct_util::convertHidlRoamingStateToLegacy(state));
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->configureNdOffload(ifname_, enable);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal(
-    uint32_t cmd_id, const std::vector<uint8_t>& ip_packet_data,
-    uint16_t ether_type, const std::array<uint8_t, 6>& src_address,
-    const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->startSendingOffloadedPacket(
-            ifname_, cmd_id, ether_type, ip_packet_data, src_address,
-            dst_address, period_in_ms);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::stopSendingKeepAlivePacketsInternal(uint32_t cmd_id) {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->stopSendingOffloadedPacket(ifname_, cmd_id);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::setScanningMacOuiInternal(
-    const std::array<uint8_t, 3>& /* oui */) {
-    // deprecated.
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() {
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->startPktFateMonitoring(ifname_);
-    return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
-WifiStaIface::getDebugTxPacketFatesInternal() {
-    legacy_hal::wifi_error legacy_status;
-    std::vector<legacy_hal::wifi_tx_report> legacy_fates;
-    std::tie(legacy_status, legacy_fates) =
-        legacy_hal_.lock()->getTxPktFates(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), {}};
-    }
-    std::vector<WifiDebugTxPacketFateReport> hidl_fates;
-    if (!hidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToHidl(
-            legacy_fates, &hidl_fates)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
-}
-
-std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
-WifiStaIface::getDebugRxPacketFatesInternal() {
-    legacy_hal::wifi_error legacy_status;
-    std::vector<legacy_hal::wifi_rx_report> legacy_fates;
-    std::tie(legacy_status, legacy_fates) =
-        legacy_hal_.lock()->getRxPktFates(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), {}};
-    }
-    std::vector<WifiDebugRxPacketFateReport> hidl_fates;
-    if (!hidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToHidl(
-            legacy_fates, &hidl_fates)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
-}
-
-WifiStatus WifiStaIface::setMacAddressInternal(
-    const std::array<uint8_t, 6>& mac) {
-    bool status = iface_util_.lock()->setMacAddress(ifname_, mac);
-    if (!status) {
-        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-    }
-    return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, std::array<uint8_t, 6>>
-WifiStaIface::getFactoryMacAddressInternal() {
-    std::array<uint8_t, 6> mac =
-        iface_util_.lock()->getFactoryMacAddress(ifname_);
-    if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 &&
-        mac[4] == 0 && mac[5] == 0) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
-}
-
-WifiStatus WifiStaIface::setScanModeInternal(bool enable) {
-    // OEM's need to implement this on their devices if needed.
-    LOG(WARNING) << "setScanModeInternal(" << enable << ") not supported";
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-}  // namespace implementation
-}  // namespace V1_5
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.5/default/wifi_sta_iface.h b/wifi/1.5/default/wifi_sta_iface.h
deleted file mode 100644
index f9058b8..0000000
--- a/wifi/1.5/default/wifi_sta_iface.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_STA_IFACE_H_
-#define WIFI_STA_IFACE_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
-#include <android/hardware/wifi/1.5/IWifiStaIface.h>
-
-#include "hidl_callback_util.h"
-#include "wifi_iface_util.h"
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_5 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * HIDL interface object used to control a STA Iface instance.
- */
-class WifiStaIface : public V1_5::IWifiStaIface {
-   public:
-    WifiStaIface(const std::string& ifname,
-                 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
-                 const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
-    // Refer to |WifiChip::invalidate()|.
-    void invalidate();
-    bool isValid();
-    std::set<sp<IWifiStaIfaceEventCallback>> getEventCallbacks();
-    std::string getName();
-
-    // HIDL methods exposed.
-    Return<void> getName(getName_cb hidl_status_cb) override;
-    Return<void> getType(getType_cb hidl_status_cb) override;
-    Return<void> registerEventCallback(
-        const sp<IWifiStaIfaceEventCallback>& callback,
-        registerEventCallback_cb hidl_status_cb) override;
-    Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
-    Return<void> getApfPacketFilterCapabilities(
-        getApfPacketFilterCapabilities_cb hidl_status_cb) override;
-    Return<void> installApfPacketFilter(
-        uint32_t cmd_id, const hidl_vec<uint8_t>& program,
-        installApfPacketFilter_cb hidl_status_cb) override;
-    Return<void> readApfPacketFilterData(
-        readApfPacketFilterData_cb hidl_status_cb) override;
-    Return<void> getBackgroundScanCapabilities(
-        getBackgroundScanCapabilities_cb hidl_status_cb) override;
-    Return<void> getValidFrequenciesForBand(
-        V1_0::WifiBand band,
-        getValidFrequenciesForBand_cb hidl_status_cb) override;
-    Return<void> startBackgroundScan(
-        uint32_t cmd_id, const StaBackgroundScanParameters& params,
-        startBackgroundScan_cb hidl_status_cb) override;
-    Return<void> stopBackgroundScan(
-        uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) override;
-    Return<void> enableLinkLayerStatsCollection(
-        bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) override;
-    Return<void> disableLinkLayerStatsCollection(
-        disableLinkLayerStatsCollection_cb hidl_status_cb) override;
-    Return<void> getLinkLayerStats(
-        getLinkLayerStats_cb hidl_status_cb) override;
-    Return<void> getLinkLayerStats_1_3(
-        getLinkLayerStats_1_3_cb hidl_status_cb) override;
-    Return<void> getLinkLayerStats_1_5(
-        getLinkLayerStats_1_5_cb hidl_status_cb) override;
-    Return<void> startRssiMonitoring(
-        uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
-        startRssiMonitoring_cb hidl_status_cb) override;
-    Return<void> stopRssiMonitoring(
-        uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) override;
-    Return<void> getRoamingCapabilities(
-        getRoamingCapabilities_cb hidl_status_cb) override;
-    Return<void> configureRoaming(const StaRoamingConfig& config,
-                                  configureRoaming_cb hidl_status_cb) override;
-    Return<void> setRoamingState(StaRoamingState state,
-                                 setRoamingState_cb hidl_status_cb) override;
-    Return<void> enableNdOffload(bool enable,
-                                 enableNdOffload_cb hidl_status_cb) override;
-    Return<void> startSendingKeepAlivePackets(
-        uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data,
-        uint16_t ether_type, const hidl_array<uint8_t, 6>& src_address,
-        const hidl_array<uint8_t, 6>& dst_address, uint32_t period_in_ms,
-        startSendingKeepAlivePackets_cb hidl_status_cb) override;
-    Return<void> stopSendingKeepAlivePackets(
-        uint32_t cmd_id,
-        stopSendingKeepAlivePackets_cb hidl_status_cb) override;
-    Return<void> setScanningMacOui(
-        const hidl_array<uint8_t, 3>& oui,
-        setScanningMacOui_cb hidl_status_cb) override;
-    Return<void> startDebugPacketFateMonitoring(
-        startDebugPacketFateMonitoring_cb hidl_status_cb) override;
-    Return<void> getDebugTxPacketFates(
-        getDebugTxPacketFates_cb hidl_status_cb) override;
-    Return<void> getDebugRxPacketFates(
-        getDebugRxPacketFates_cb hidl_status_cb) override;
-    Return<void> setMacAddress(const hidl_array<uint8_t, 6>& mac,
-                               setMacAddress_cb hidl_status_cb) override;
-    Return<void> getFactoryMacAddress(
-        getFactoryMacAddress_cb hidl_status_cb) override;
-    Return<void> setScanMode(bool enable,
-                             setScanMode_cb hidl_status_cb) override;
-
-   private:
-    // Corresponding worker functions for the HIDL methods.
-    std::pair<WifiStatus, std::string> getNameInternal();
-    std::pair<WifiStatus, IfaceType> getTypeInternal();
-    WifiStatus registerEventCallbackInternal(
-        const sp<IWifiStaIfaceEventCallback>& callback);
-    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
-    std::pair<WifiStatus, StaApfPacketFilterCapabilities>
-    getApfPacketFilterCapabilitiesInternal();
-    WifiStatus installApfPacketFilterInternal(
-        uint32_t cmd_id, const std::vector<uint8_t>& program);
-    std::pair<WifiStatus, std::vector<uint8_t>>
-    readApfPacketFilterDataInternal();
-    std::pair<WifiStatus, StaBackgroundScanCapabilities>
-    getBackgroundScanCapabilitiesInternal();
-    std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-    getValidFrequenciesForBandInternal(V1_0::WifiBand band);
-    WifiStatus startBackgroundScanInternal(
-        uint32_t cmd_id, const StaBackgroundScanParameters& params);
-    WifiStatus stopBackgroundScanInternal(uint32_t cmd_id);
-    WifiStatus enableLinkLayerStatsCollectionInternal(bool debug);
-    WifiStatus disableLinkLayerStatsCollectionInternal();
-    std::pair<WifiStatus, V1_0::StaLinkLayerStats> getLinkLayerStatsInternal();
-    std::pair<WifiStatus, V1_3::StaLinkLayerStats>
-    getLinkLayerStatsInternal_1_3();
-    std::pair<WifiStatus, V1_5::StaLinkLayerStats>
-    getLinkLayerStatsInternal_1_5();
-    WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi,
-                                           int32_t min_rssi);
-    WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id);
-    std::pair<WifiStatus, StaRoamingCapabilities>
-    getRoamingCapabilitiesInternal();
-    WifiStatus configureRoamingInternal(const StaRoamingConfig& config);
-    WifiStatus setRoamingStateInternal(StaRoamingState state);
-    WifiStatus enableNdOffloadInternal(bool enable);
-    WifiStatus startSendingKeepAlivePacketsInternal(
-        uint32_t cmd_id, const std::vector<uint8_t>& ip_packet_data,
-        uint16_t ether_type, const std::array<uint8_t, 6>& src_address,
-        const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms);
-    WifiStatus stopSendingKeepAlivePacketsInternal(uint32_t cmd_id);
-    WifiStatus setScanningMacOuiInternal(const std::array<uint8_t, 3>& oui);
-    WifiStatus startDebugPacketFateMonitoringInternal();
-    std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
-    getDebugTxPacketFatesInternal();
-    std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
-    getDebugRxPacketFatesInternal();
-    WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
-    std::pair<WifiStatus, std::array<uint8_t, 6>>
-    getFactoryMacAddressInternal();
-    WifiStatus setScanModeInternal(bool enable);
-
-    std::string ifname_;
-    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-    std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
-    bool is_valid_;
-    hidl_callback_util::HidlCallbackHandler<IWifiStaIfaceEventCallback>
-        event_cb_handler_;
-
-    DISALLOW_COPY_AND_ASSIGN(WifiStaIface);
-};
-
-}  // namespace implementation
-}  // namespace V1_5
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_STA_IFACE_H_
diff --git a/wifi/1.6/Android.bp b/wifi/1.6/Android.bp
new file mode 100644
index 0000000..d293c73
--- /dev/null
+++ b/wifi/1.6/Android.bp
@@ -0,0 +1,32 @@
+// 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.wifi@1.6",
+    root: "android.hardware",
+    srcs: [
+        "IWifi.hal",
+    ],
+    interfaces: [
+        "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.hidl.base@1.0",
+    ],
+    gen_java: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.wifi",
+    ],
+}
diff --git a/wifi/1.6/IWifi.hal b/wifi/1.6/IWifi.hal
new file mode 100644
index 0000000..0123e6c
--- /dev/null
+++ b/wifi/1.6/IWifi.hal
@@ -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.wifi@1.6;
+
+import @1.5::IWifi;
+
+/**
+ * This is the root of the HAL module and is the interface returned when
+ * loading an implementation of the Wi-Fi HAL. There must be at most one
+ * module loaded in the system.
+ * IWifi.getChip() must return @1.5::IWifiChip
+ */
+interface IWifi extends @1.5::IWifi {};
diff --git a/wifi/1.5/default/Android.bp b/wifi/1.6/default/Android.bp
similarity index 97%
rename from wifi/1.5/default/Android.bp
rename to wifi/1.6/default/Android.bp
index 6333b6e..d48d183 100644
--- a/wifi/1.5/default/Android.bp
+++ b/wifi/1.6/default/Android.bp
@@ -33,6 +33,7 @@
         "android.hardware.wifi@1.3",
         "android.hardware.wifi@1.4",
         "android.hardware.wifi@1.5",
+        "android.hardware.wifi@1.6",
         "libbase",
         "libcutils",
         "libhidlbase",
@@ -84,6 +85,7 @@
         "android.hardware.wifi@1.3",
         "android.hardware.wifi@1.4",
         "android.hardware.wifi@1.5",
+        "android.hardware.wifi@1.6",
         "libbase",
         "libcutils",
         "libhidlbase",
diff --git a/wifi/1.5/default/Android.mk b/wifi/1.6/default/Android.mk
similarity index 96%
rename from wifi/1.5/default/Android.mk
rename to wifi/1.6/default/Android.mk
index 1997b22..ca1c022 100644
--- a/wifi/1.5/default/Android.mk
+++ b/wifi/1.6/default/Android.mk
@@ -77,7 +77,8 @@
     android.hardware.wifi@1.2 \
     android.hardware.wifi@1.3 \
     android.hardware.wifi@1.4 \
-    android.hardware.wifi@1.5
+    android.hardware.wifi@1.5 \
+    android.hardware.wifi@1.6
 LOCAL_C_INCLUDES += $(TOP)/external/libxml2/include
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
 include $(BUILD_STATIC_LIBRARY)
@@ -111,7 +112,8 @@
     android.hardware.wifi@1.2 \
     android.hardware.wifi@1.3 \
     android.hardware.wifi@1.4 \
-    android.hardware.wifi@1.5
+    android.hardware.wifi@1.5 \
+    android.hardware.wifi@1.6
 LOCAL_STATIC_LIBRARIES := \
     android.hardware.wifi@1.0-service-lib
 LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc
@@ -148,7 +150,8 @@
     android.hardware.wifi@1.2 \
     android.hardware.wifi@1.3 \
     android.hardware.wifi@1.4 \
-    android.hardware.wifi@1.5
+    android.hardware.wifi@1.5 \
+    android.hardware.wifi@1.6
 LOCAL_STATIC_LIBRARIES := \
     android.hardware.wifi@1.0-service-lib
 LOCAL_INIT_RC := android.hardware.wifi@1.0-service-lazy.rc
@@ -185,6 +188,7 @@
     android.hardware.wifi@1.3 \
     android.hardware.wifi@1.4 \
     android.hardware.wifi@1.5 \
+    android.hardware.wifi@1.6 \
     android.hardware.wifi@1.0-service-lib
 LOCAL_SHARED_LIBRARIES := \
     libbase \
diff --git a/wifi/1.5/default/OWNERS b/wifi/1.6/default/OWNERS
similarity index 100%
rename from wifi/1.5/default/OWNERS
rename to wifi/1.6/default/OWNERS
diff --git a/wifi/1.5/default/THREADING.README b/wifi/1.6/default/THREADING.README
similarity index 100%
rename from wifi/1.5/default/THREADING.README
rename to wifi/1.6/default/THREADING.README
diff --git a/wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc b/wifi/1.6/default/android.hardware.wifi@1.0-service-lazy.rc
similarity index 90%
rename from wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc
rename to wifi/1.6/default/android.hardware.wifi@1.0-service-lazy.rc
index bc6bb6a..ee8c818 100644
--- a/wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc
+++ b/wifi/1.6/default/android.hardware.wifi@1.0-service-lazy.rc
@@ -5,6 +5,7 @@
     interface android.hardware.wifi@1.3::IWifi default
     interface android.hardware.wifi@1.4::IWifi default
     interface android.hardware.wifi@1.5::IWifi default
+    interface android.hardware.wifi@1.6::IWifi default
     oneshot
     disabled
     class hal
diff --git a/wifi/1.5/default/android.hardware.wifi@1.0-service.rc b/wifi/1.6/default/android.hardware.wifi@1.0-service.rc
similarity index 89%
rename from wifi/1.5/default/android.hardware.wifi@1.0-service.rc
rename to wifi/1.6/default/android.hardware.wifi@1.0-service.rc
index 05706ef..18f40d0 100644
--- a/wifi/1.5/default/android.hardware.wifi@1.0-service.rc
+++ b/wifi/1.6/default/android.hardware.wifi@1.0-service.rc
@@ -5,6 +5,7 @@
     interface android.hardware.wifi@1.3::IWifi default
     interface android.hardware.wifi@1.4::IWifi default
     interface android.hardware.wifi@1.5::IWifi default
+    interface android.hardware.wifi@1.6::IWifi default
     class hal
     capabilities NET_ADMIN NET_RAW SYS_MODULE
     user wifi
diff --git a/wifi/1.5/default/android.hardware.wifi@1.0-service.xml b/wifi/1.6/default/android.hardware.wifi@1.0-service.xml
similarity index 89%
rename from wifi/1.5/default/android.hardware.wifi@1.0-service.xml
rename to wifi/1.6/default/android.hardware.wifi@1.0-service.xml
index 88dd1e3..771fbaa 100644
--- a/wifi/1.5/default/android.hardware.wifi@1.0-service.xml
+++ b/wifi/1.6/default/android.hardware.wifi@1.0-service.xml
@@ -2,7 +2,7 @@
     <hal format="hidl">
         <name>android.hardware.wifi</name>
         <transport>hwbinder</transport>
-        <version>1.5</version>
+        <version>1.6</version>
         <interface>
             <name>IWifi</name>
             <instance>default</instance>
diff --git a/wifi/1.5/default/hidl_callback_util.h b/wifi/1.6/default/hidl_callback_util.h
similarity index 88%
rename from wifi/1.5/default/hidl_callback_util.h
rename to wifi/1.6/default/hidl_callback_util.h
index d144658..3ac54c1 100644
--- a/wifi/1.5/default/hidl_callback_util.h
+++ b/wifi/1.6/default/hidl_callback_util.h
@@ -29,20 +29,18 @@
 // callbacks stored in HidlCallbackHandler.
 template <typename CallbackType>
 class HidlDeathHandler : public android::hardware::hidl_death_recipient {
-   public:
+  public:
     HidlDeathHandler(const on_death_cb_function& user_cb_function)
         : cb_function_(user_cb_function) {}
     ~HidlDeathHandler() = default;
 
     // Death notification for callbacks.
-    void serviceDied(
-        uint64_t cookie,
-        const android::wp<android::hidl::base::V1_0::IBase>& /* who */)
-        override {
+    void serviceDied(uint64_t cookie,
+                     const android::wp<android::hidl::base::V1_0::IBase>& /* who */) override {
         cb_function_(cookie);
     }
 
-   private:
+  private:
     on_death_cb_function cb_function_;
 
     DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler);
@@ -52,18 +50,17 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace hidl_callback_util {
 template <typename CallbackType>
 // Provides a class to manage callbacks for the various HIDL interfaces and
 // handle the death of the process hosting each callback.
 class HidlCallbackHandler {
-   public:
+  public:
     HidlCallbackHandler()
         : death_handler_(new HidlDeathHandler<CallbackType>(
-              std::bind(&HidlCallbackHandler::onObjectDeath, this,
-                        std::placeholders::_1))) {}
+                  std::bind(&HidlCallbackHandler::onObjectDeath, this, std::placeholders::_1))) {}
     ~HidlCallbackHandler() = default;
 
     bool addCallback(const sp<CallbackType>& cb) {
@@ -83,9 +80,7 @@
         return true;
     }
 
-    const std::set<android::sp<CallbackType>>& getCallbacks() {
-        return cb_set_;
-    }
+    const std::set<android::sp<CallbackType>>& getCallbacks() { return cb_set_; }
 
     // Death notification for callbacks.
     void onObjectDeath(uint64_t cookie) {
@@ -108,7 +103,7 @@
         cb_set_.clear();
     }
 
-   private:
+  private:
     std::set<sp<CallbackType>> cb_set_;
     sp<HidlDeathHandler<CallbackType>> death_handler_;
 
@@ -117,7 +112,7 @@
 
 }  // namespace hidl_callback_util
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/hidl_return_util.h b/wifi/1.6/default/hidl_return_util.h
similarity index 77%
rename from wifi/1.5/default/hidl_return_util.h
rename to wifi/1.6/default/hidl_return_util.h
index 4455185..a0efac2 100644
--- a/wifi/1.5/default/hidl_return_util.h
+++ b/wifi/1.6/default/hidl_return_util.h
@@ -23,7 +23,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace hidl_return_util {
 using namespace android::hardware::wifi::V1_0;
@@ -40,9 +40,9 @@
  */
 // Use for HIDL methods which return only an instance of WifiStatus.
 template <typename ObjT, typename WorkFuncT, typename... Args>
-Return<void> validateAndCall(
-    ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
-    const std::function<void(const WifiStatus&)>& hidl_cb, Args&&... args) {
+Return<void> validateAndCall(ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
+                             const std::function<void(const WifiStatus&)>& hidl_cb,
+                             Args&&... args) {
     const auto lock = hidl_sync_util::acquireGlobalLock();
     if (obj->isValid()) {
         hidl_cb((obj->*work)(std::forward<Args>(args)...));
@@ -56,9 +56,10 @@
 // This version passes the global lock acquired to the body of the method.
 // Note: Only used by IWifi::stop() currently.
 template <typename ObjT, typename WorkFuncT, typename... Args>
-Return<void> validateAndCallWithLock(
-    ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
-    const std::function<void(const WifiStatus&)>& hidl_cb, Args&&... args) {
+Return<void> validateAndCallWithLock(ObjT* obj, WifiStatusCode status_code_if_invalid,
+                                     WorkFuncT&& work,
+                                     const std::function<void(const WifiStatus&)>& hidl_cb,
+                                     Args&&... args) {
     auto lock = hidl_sync_util::acquireGlobalLock();
     if (obj->isValid()) {
         hidl_cb((obj->*work)(&lock, std::forward<Args>(args)...));
@@ -71,10 +72,9 @@
 // Use for HIDL methods which return instance of WifiStatus and a single return
 // value.
 template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
-Return<void> validateAndCall(
-    ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
-    const std::function<void(const WifiStatus&, ReturnT)>& hidl_cb,
-    Args&&... args) {
+Return<void> validateAndCall(ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
+                             const std::function<void(const WifiStatus&, ReturnT)>& hidl_cb,
+                             Args&&... args) {
     const auto lock = hidl_sync_util::acquireGlobalLock();
     if (obj->isValid()) {
         const auto& ret_pair = (obj->*work)(std::forward<Args>(args)...);
@@ -90,12 +90,10 @@
 
 // Use for HIDL methods which return instance of WifiStatus and 2 return
 // values.
-template <typename ObjT, typename WorkFuncT, typename ReturnT1,
-          typename ReturnT2, typename... Args>
+template <typename ObjT, typename WorkFuncT, typename ReturnT1, typename ReturnT2, typename... Args>
 Return<void> validateAndCall(
-    ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
-    const std::function<void(const WifiStatus&, ReturnT1, ReturnT2)>& hidl_cb,
-    Args&&... args) {
+        ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
+        const std::function<void(const WifiStatus&, ReturnT1, ReturnT2)>& hidl_cb, Args&&... args) {
     const auto lock = hidl_sync_util::acquireGlobalLock();
     if (obj->isValid()) {
         const auto& ret_tuple = (obj->*work)(std::forward<Args>(args)...);
@@ -113,7 +111,7 @@
 
 }  // namespace hidl_return_util
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/hidl_struct_util.cpp b/wifi/1.6/default/hidl_struct_util.cpp
similarity index 63%
rename from wifi/1.5/default/hidl_struct_util.cpp
rename to wifi/1.6/default/hidl_struct_util.cpp
index 338a8f1..3489c9e 100644
--- a/wifi/1.5/default/hidl_struct_util.cpp
+++ b/wifi/1.6/default/hidl_struct_util.cpp
@@ -22,12 +22,13 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace hidl_struct_util {
 
-WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl(
-    legacy_hal::wifi_channel_width type);
+using V1_5::NanConfigRequestSupplemental;
+
+WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl(legacy_hal::wifi_channel_width type);
 
 hidl_string safeConvertChar(const char* str, size_t max_len) {
     const char* c = str;
@@ -39,8 +40,7 @@
     return hidl_string(str, size);
 }
 
-IWifiChip::ChipCapabilityMask convertLegacyLoggerFeatureToHidlChipCapability(
-    uint32_t feature) {
+IWifiChip::ChipCapabilityMask convertLegacyLoggerFeatureToHidlChipCapability(uint32_t feature) {
     using HidlChipCaps = IWifiChip::ChipCapabilityMask;
     switch (feature) {
         case legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED:
@@ -58,8 +58,8 @@
     return {};
 }
 
-IWifiStaIface::StaIfaceCapabilityMask
-convertLegacyLoggerFeatureToHidlStaIfaceCapability(uint32_t feature) {
+IWifiStaIface::StaIfaceCapabilityMask convertLegacyLoggerFeatureToHidlStaIfaceCapability(
+        uint32_t feature) {
     using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
     switch (feature) {
         case legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED:
@@ -69,8 +69,7 @@
     return {};
 }
 
-V1_5::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability(
-    uint64_t feature) {
+V1_5::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability(uint64_t feature) {
     using HidlChipCaps = V1_5::IWifiChip::ChipCapabilityMask;
     switch (feature) {
         case WIFI_FEATURE_SET_TX_POWER_LIMIT:
@@ -92,8 +91,8 @@
     return {};
 }
 
-IWifiStaIface::StaIfaceCapabilityMask
-convertLegacyFeatureToHidlStaIfaceCapability(uint64_t feature) {
+IWifiStaIface::StaIfaceCapabilityMask convertLegacyFeatureToHidlStaIfaceCapability(
+        uint64_t feature) {
     using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
     switch (feature) {
         case WIFI_FEATURE_GSCAN:
@@ -127,9 +126,9 @@
     return {};
 }
 
-bool convertLegacyFeaturesToHidlChipCapabilities(
-    uint64_t legacy_feature_set, uint32_t legacy_logger_feature_set,
-    uint32_t* hidl_caps) {
+bool convertLegacyFeaturesToHidlChipCapabilities(uint64_t legacy_feature_set,
+                                                 uint32_t legacy_logger_feature_set,
+                                                 uint32_t* hidl_caps) {
     if (!hidl_caps) {
         return false;
     }
@@ -141,8 +140,7 @@
                                legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED,
                                legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED}) {
         if (feature & legacy_logger_feature_set) {
-            *hidl_caps |=
-                convertLegacyLoggerFeatureToHidlChipCapability(feature);
+            *hidl_caps |= convertLegacyLoggerFeatureToHidlChipCapability(feature);
         }
     }
     std::vector<uint64_t> features = {WIFI_FEATURE_SET_TX_POWER_LIMIT,
@@ -166,8 +164,7 @@
     return true;
 }
 
-WifiDebugRingBufferFlags convertLegacyDebugRingBufferFlagsToHidl(
-    uint32_t flag) {
+WifiDebugRingBufferFlags convertLegacyDebugRingBufferFlagsToHidl(uint32_t flag) {
     switch (flag) {
         case WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES:
             return WifiDebugRingBufferFlags::HAS_BINARY_ENTRIES;
@@ -179,22 +176,20 @@
 }
 
 bool convertLegacyDebugRingBufferStatusToHidl(
-    const legacy_hal::wifi_ring_buffer_status& legacy_status,
-    WifiDebugRingBufferStatus* hidl_status) {
+        const legacy_hal::wifi_ring_buffer_status& legacy_status,
+        WifiDebugRingBufferStatus* hidl_status) {
     if (!hidl_status) {
         return false;
     }
     *hidl_status = {};
-    hidl_status->ringName =
-        safeConvertChar(reinterpret_cast<const char*>(legacy_status.name),
-                        sizeof(legacy_status.name));
+    hidl_status->ringName = safeConvertChar(reinterpret_cast<const char*>(legacy_status.name),
+                                            sizeof(legacy_status.name));
     hidl_status->flags = 0;
-    for (const auto flag : {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES,
-                            WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES}) {
+    for (const auto flag :
+         {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES, WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES}) {
         if (flag & legacy_status.flags) {
-            hidl_status->flags |= static_cast<
-                std::underlying_type<WifiDebugRingBufferFlags>::type>(
-                convertLegacyDebugRingBufferFlagsToHidl(flag));
+            hidl_status->flags |= static_cast<std::underlying_type<WifiDebugRingBufferFlags>::type>(
+                    convertLegacyDebugRingBufferFlagsToHidl(flag));
         }
     }
     hidl_status->ringId = legacy_status.ring_id;
@@ -202,28 +197,25 @@
     // Calculate free size of the ring the buffer. We don't need to send the
     // exact read/write pointers that were there in the legacy HAL interface.
     if (legacy_status.written_bytes >= legacy_status.read_bytes) {
-        hidl_status->freeSizeInBytes =
-            legacy_status.ring_buffer_byte_size -
-            (legacy_status.written_bytes - legacy_status.read_bytes);
+        hidl_status->freeSizeInBytes = legacy_status.ring_buffer_byte_size -
+                                       (legacy_status.written_bytes - legacy_status.read_bytes);
     } else {
-        hidl_status->freeSizeInBytes =
-            legacy_status.read_bytes - legacy_status.written_bytes;
+        hidl_status->freeSizeInBytes = legacy_status.read_bytes - legacy_status.written_bytes;
     }
     hidl_status->verboseLevel = legacy_status.verbose_level;
     return true;
 }
 
 bool convertLegacyVectorOfDebugRingBufferStatusToHidl(
-    const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
-    std::vector<WifiDebugRingBufferStatus>* hidl_status_vec) {
+        const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
+        std::vector<WifiDebugRingBufferStatus>* hidl_status_vec) {
     if (!hidl_status_vec) {
         return false;
     }
     *hidl_status_vec = {};
     for (const auto& legacy_status : legacy_status_vec) {
         WifiDebugRingBufferStatus hidl_status;
-        if (!convertLegacyDebugRingBufferStatusToHidl(legacy_status,
-                                                      &hidl_status)) {
+        if (!convertLegacyDebugRingBufferStatusToHidl(legacy_status, &hidl_status)) {
             return false;
         }
         hidl_status_vec->push_back(hidl_status);
@@ -231,52 +223,44 @@
     return true;
 }
 
-bool convertLegacyWakeReasonStatsToHidl(
-    const legacy_hal::WakeReasonStats& legacy_stats,
-    WifiDebugHostWakeReasonStats* hidl_stats) {
+bool convertLegacyWakeReasonStatsToHidl(const legacy_hal::WakeReasonStats& legacy_stats,
+                                        WifiDebugHostWakeReasonStats* hidl_stats) {
     if (!hidl_stats) {
         return false;
     }
     *hidl_stats = {};
-    hidl_stats->totalCmdEventWakeCnt =
-        legacy_stats.wake_reason_cnt.total_cmd_event_wake;
+    hidl_stats->totalCmdEventWakeCnt = legacy_stats.wake_reason_cnt.total_cmd_event_wake;
     hidl_stats->cmdEventWakeCntPerType = legacy_stats.cmd_event_wake_cnt;
-    hidl_stats->totalDriverFwLocalWakeCnt =
-        legacy_stats.wake_reason_cnt.total_driver_fw_local_wake;
-    hidl_stats->driverFwLocalWakeCntPerType =
-        legacy_stats.driver_fw_local_wake_cnt;
-    hidl_stats->totalRxPacketWakeCnt =
-        legacy_stats.wake_reason_cnt.total_rx_data_wake;
+    hidl_stats->totalDriverFwLocalWakeCnt = legacy_stats.wake_reason_cnt.total_driver_fw_local_wake;
+    hidl_stats->driverFwLocalWakeCntPerType = legacy_stats.driver_fw_local_wake_cnt;
+    hidl_stats->totalRxPacketWakeCnt = legacy_stats.wake_reason_cnt.total_rx_data_wake;
     hidl_stats->rxPktWakeDetails.rxUnicastCnt =
-        legacy_stats.wake_reason_cnt.rx_wake_details.rx_unicast_cnt;
+            legacy_stats.wake_reason_cnt.rx_wake_details.rx_unicast_cnt;
     hidl_stats->rxPktWakeDetails.rxMulticastCnt =
-        legacy_stats.wake_reason_cnt.rx_wake_details.rx_multicast_cnt;
+            legacy_stats.wake_reason_cnt.rx_wake_details.rx_multicast_cnt;
     hidl_stats->rxPktWakeDetails.rxBroadcastCnt =
-        legacy_stats.wake_reason_cnt.rx_wake_details.rx_broadcast_cnt;
+            legacy_stats.wake_reason_cnt.rx_wake_details.rx_broadcast_cnt;
     hidl_stats->rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt =
-        legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
-            .ipv4_rx_multicast_addr_cnt;
+            legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt;
     hidl_stats->rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt =
-        legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
-            .ipv6_rx_multicast_addr_cnt;
+            legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt;
     hidl_stats->rxMulticastPkWakeDetails.otherRxMulticastAddrCnt =
-        legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
-            .other_rx_multicast_addr_cnt;
+            legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt;
     hidl_stats->rxIcmpPkWakeDetails.icmpPkt =
-        legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp_pkt;
+            legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp_pkt;
     hidl_stats->rxIcmpPkWakeDetails.icmp6Pkt =
-        legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_pkt;
+            legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_pkt;
     hidl_stats->rxIcmpPkWakeDetails.icmp6Ra =
-        legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ra;
+            legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ra;
     hidl_stats->rxIcmpPkWakeDetails.icmp6Na =
-        legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_na;
+            legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_na;
     hidl_stats->rxIcmpPkWakeDetails.icmp6Ns =
-        legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ns;
+            legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ns;
     return true;
 }
 
 legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
-    V1_1::IWifiChip::TxPowerScenario hidl_scenario) {
+        V1_1::IWifiChip::TxPowerScenario hidl_scenario) {
     switch (hidl_scenario) {
         // This is the only supported scenario for V1_1
         case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL:
@@ -286,7 +270,7 @@
 }
 
 legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2(
-    V1_2::IWifiChip::TxPowerScenario hidl_scenario) {
+        V1_2::IWifiChip::TxPowerScenario hidl_scenario) {
     switch (hidl_scenario) {
         // This is the only supported scenario for V1_1
         case V1_2::IWifiChip::TxPowerScenario::VOICE_CALL:
@@ -305,7 +289,7 @@
 }
 
 legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy(
-    V1_3::IWifiChip::LatencyMode hidl_latency_mode) {
+        V1_3::IWifiChip::LatencyMode hidl_latency_mode) {
     switch (hidl_latency_mode) {
         case V1_3::IWifiChip::LatencyMode::NORMAL:
             return legacy_hal::WIFI_LATENCY_MODE_NORMAL;
@@ -316,8 +300,8 @@
 }
 
 bool convertLegacyWifiMacInfoToHidl(
-    const legacy_hal::WifiMacInfo& legacy_mac_info,
-    V1_4::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) {
+        const legacy_hal::WifiMacInfo& legacy_mac_info,
+        V1_4::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) {
     if (!hidl_radio_mode_info) {
         return false;
     }
@@ -366,24 +350,20 @@
             return legacy_hal::WLAN_MAC_5_0_BAND;
         case V1_5::WifiBand::BAND_24GHZ_5GHZ:
         case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS:
-            return (legacy_hal::WLAN_MAC_2_4_BAND |
-                    legacy_hal::WLAN_MAC_5_0_BAND);
+            return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND);
         case V1_5::WifiBand::BAND_6GHZ:
             return legacy_hal::WLAN_MAC_6_0_BAND;
         case V1_5::WifiBand::BAND_5GHZ_6GHZ:
-            return (legacy_hal::WLAN_MAC_5_0_BAND |
-                    legacy_hal::WLAN_MAC_6_0_BAND);
+            return (legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_6_0_BAND);
         case V1_5::WifiBand::BAND_24GHZ_5GHZ_6GHZ:
         case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS_6GHZ:
-            return (legacy_hal::WLAN_MAC_2_4_BAND |
-                    legacy_hal::WLAN_MAC_5_0_BAND |
+            return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND |
                     legacy_hal::WLAN_MAC_6_0_BAND);
         case V1_5::WifiBand::BAND_60GHZ:
             return legacy_hal::WLAN_MAC_60_0_BAND;
         default:
-            return (
-                legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND |
-                legacy_hal::WLAN_MAC_6_0_BAND | legacy_hal::WLAN_MAC_60_0_BAND);
+            return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND |
+                    legacy_hal::WLAN_MAC_6_0_BAND | legacy_hal::WLAN_MAC_60_0_BAND);
     }
 }
 
@@ -447,45 +427,41 @@
 
 uint32_t convertHidlUsableChannelFilterToLegacy(uint32_t hidl_filter_mask) {
     uint32_t legacy_filter_mask = 0;
-    if (hidl_filter_mask &
-        IWifiChip::UsableChannelFilter::CELLULAR_COEXISTENCE) {
-        legacy_filter_mask |=
-            legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE;
+    if (hidl_filter_mask & V1_5::IWifiChip::UsableChannelFilter::CELLULAR_COEXISTENCE) {
+        legacy_filter_mask |= legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE;
     }
-    if (hidl_filter_mask & IWifiChip::UsableChannelFilter::CONCURRENCY) {
-        legacy_filter_mask |=
-            legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY;
+    if (hidl_filter_mask & V1_5::IWifiChip::UsableChannelFilter::CONCURRENCY) {
+        legacy_filter_mask |= legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY;
     }
     return legacy_filter_mask;
 }
 
 bool convertLegacyWifiUsableChannelToHidl(
-    const legacy_hal::wifi_usable_channel& legacy_usable_channel,
-    V1_5::WifiUsableChannel* hidl_usable_channel) {
+        const legacy_hal::wifi_usable_channel& legacy_usable_channel,
+        V1_5::WifiUsableChannel* hidl_usable_channel) {
     if (!hidl_usable_channel) {
         return false;
     }
     *hidl_usable_channel = {};
     hidl_usable_channel->channel = legacy_usable_channel.freq;
     hidl_usable_channel->channelBandwidth =
-        convertLegacyWifiChannelWidthToHidl(legacy_usable_channel.width);
-    hidl_usable_channel->ifaceModeMask = convertLegacyWifiInterfaceModeToHidl(
-        legacy_usable_channel.iface_mode_mask);
+            convertLegacyWifiChannelWidthToHidl(legacy_usable_channel.width);
+    hidl_usable_channel->ifaceModeMask =
+            convertLegacyWifiInterfaceModeToHidl(legacy_usable_channel.iface_mode_mask);
 
     return true;
 }
 
 bool convertLegacyWifiUsableChannelsToHidl(
-    const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels,
-    std::vector<V1_5::WifiUsableChannel>* hidl_usable_channels) {
+        const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels,
+        std::vector<V1_5::WifiUsableChannel>* hidl_usable_channels) {
     if (!hidl_usable_channels) {
         return false;
     }
     *hidl_usable_channels = {};
     for (const auto& legacy_usable_channel : legacy_usable_channels) {
         V1_5::WifiUsableChannel hidl_usable_channel;
-        if (!convertLegacyWifiUsableChannelToHidl(legacy_usable_channel,
-                                                  &hidl_usable_channel)) {
+        if (!convertLegacyWifiUsableChannelToHidl(legacy_usable_channel, &hidl_usable_channel)) {
             return false;
         }
         hidl_usable_channels->push_back(hidl_usable_channel);
@@ -494,9 +470,8 @@
 }
 
 bool convertLegacyWifiMacInfosToHidl(
-    const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
-    std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>*
-        hidl_radio_mode_infos) {
+        const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
+        std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos) {
     if (!hidl_radio_mode_infos) {
         return false;
     }
@@ -504,8 +479,7 @@
 
     for (const auto& legacy_mac_info : legacy_mac_infos) {
         V1_4::IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info;
-        if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info,
-                                            &hidl_radio_mode_info)) {
+        if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info, &hidl_radio_mode_info)) {
             return false;
         }
         hidl_radio_mode_infos->push_back(hidl_radio_mode_info);
@@ -513,9 +487,9 @@
     return true;
 }
 
-bool convertLegacyFeaturesToHidlStaCapabilities(
-    uint64_t legacy_feature_set, uint32_t legacy_logger_feature_set,
-    uint32_t* hidl_caps) {
+bool convertLegacyFeaturesToHidlStaCapabilities(uint64_t legacy_feature_set,
+                                                uint32_t legacy_logger_feature_set,
+                                                uint32_t* hidl_caps) {
     if (!hidl_caps) {
         return false;
     }
@@ -523,17 +497,14 @@
     using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
     for (const auto feature : {legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED}) {
         if (feature & legacy_logger_feature_set) {
-            *hidl_caps |=
-                convertLegacyLoggerFeatureToHidlStaIfaceCapability(feature);
+            *hidl_caps |= convertLegacyLoggerFeatureToHidlStaIfaceCapability(feature);
         }
     }
     for (const auto feature :
-         {WIFI_FEATURE_GSCAN, WIFI_FEATURE_LINK_LAYER_STATS,
-          WIFI_FEATURE_RSSI_MONITOR, WIFI_FEATURE_CONTROL_ROAMING,
-          WIFI_FEATURE_IE_WHITELIST, WIFI_FEATURE_SCAN_RAND,
-          WIFI_FEATURE_INFRA_5G, WIFI_FEATURE_HOTSPOT, WIFI_FEATURE_PNO,
-          WIFI_FEATURE_TDLS, WIFI_FEATURE_TDLS_OFFCHANNEL,
-          WIFI_FEATURE_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE}) {
+         {WIFI_FEATURE_GSCAN, WIFI_FEATURE_LINK_LAYER_STATS, WIFI_FEATURE_RSSI_MONITOR,
+          WIFI_FEATURE_CONTROL_ROAMING, WIFI_FEATURE_IE_WHITELIST, WIFI_FEATURE_SCAN_RAND,
+          WIFI_FEATURE_INFRA_5G, WIFI_FEATURE_HOTSPOT, WIFI_FEATURE_PNO, WIFI_FEATURE_TDLS,
+          WIFI_FEATURE_TDLS_OFFCHANNEL, WIFI_FEATURE_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE}) {
         if (feature & legacy_feature_set) {
             *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature);
         }
@@ -544,9 +515,8 @@
     return true;
 }
 
-bool convertLegacyApfCapabilitiesToHidl(
-    const legacy_hal::PacketFilterCapabilities& legacy_caps,
-    StaApfPacketFilterCapabilities* hidl_caps) {
+bool convertLegacyApfCapabilitiesToHidl(const legacy_hal::PacketFilterCapabilities& legacy_caps,
+                                        StaApfPacketFilterCapabilities* hidl_caps) {
     if (!hidl_caps) {
         return false;
     }
@@ -557,7 +527,7 @@
 }
 
 uint8_t convertHidlGscanReportEventFlagToLegacy(
-    StaBackgroundScanBucketEventReportSchemeMask hidl_flag) {
+        StaBackgroundScanBucketEventReportSchemeMask hidl_flag) {
     using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask;
     switch (hidl_flag) {
         case HidlFlag::EACH_SCAN:
@@ -581,9 +551,8 @@
     return {};
 }
 
-bool convertLegacyGscanCapabilitiesToHidl(
-    const legacy_hal::wifi_gscan_capabilities& legacy_caps,
-    StaBackgroundScanCapabilities* hidl_caps) {
+bool convertLegacyGscanCapabilitiesToHidl(const legacy_hal::wifi_gscan_capabilities& legacy_caps,
+                                          StaBackgroundScanCapabilities* hidl_caps) {
     if (!hidl_caps) {
         return false;
     }
@@ -615,73 +584,61 @@
     CHECK(false);
 }
 
-bool convertHidlGscanParamsToLegacy(
-    const StaBackgroundScanParameters& hidl_scan_params,
-    legacy_hal::wifi_scan_cmd_params* legacy_scan_params) {
+bool convertHidlGscanParamsToLegacy(const StaBackgroundScanParameters& hidl_scan_params,
+                                    legacy_hal::wifi_scan_cmd_params* legacy_scan_params) {
     if (!legacy_scan_params) {
         return false;
     }
     *legacy_scan_params = {};
     legacy_scan_params->base_period = hidl_scan_params.basePeriodInMs;
     legacy_scan_params->max_ap_per_scan = hidl_scan_params.maxApPerScan;
-    legacy_scan_params->report_threshold_percent =
-        hidl_scan_params.reportThresholdPercent;
-    legacy_scan_params->report_threshold_num_scans =
-        hidl_scan_params.reportThresholdNumScans;
+    legacy_scan_params->report_threshold_percent = hidl_scan_params.reportThresholdPercent;
+    legacy_scan_params->report_threshold_num_scans = hidl_scan_params.reportThresholdNumScans;
     if (hidl_scan_params.buckets.size() > MAX_BUCKETS) {
         return false;
     }
     legacy_scan_params->num_buckets = hidl_scan_params.buckets.size();
-    for (uint32_t bucket_idx = 0; bucket_idx < hidl_scan_params.buckets.size();
-         bucket_idx++) {
+    for (uint32_t bucket_idx = 0; bucket_idx < hidl_scan_params.buckets.size(); bucket_idx++) {
         const StaBackgroundScanBucketParameters& hidl_bucket_spec =
-            hidl_scan_params.buckets[bucket_idx];
+                hidl_scan_params.buckets[bucket_idx];
         legacy_hal::wifi_scan_bucket_spec& legacy_bucket_spec =
-            legacy_scan_params->buckets[bucket_idx];
+                legacy_scan_params->buckets[bucket_idx];
         if (hidl_bucket_spec.bucketIdx >= MAX_BUCKETS) {
             return false;
         }
         legacy_bucket_spec.bucket = hidl_bucket_spec.bucketIdx;
-        legacy_bucket_spec.band =
-            convertHidlWifiBandToLegacy(hidl_bucket_spec.band);
+        legacy_bucket_spec.band = convertHidlWifiBandToLegacy(hidl_bucket_spec.band);
         legacy_bucket_spec.period = hidl_bucket_spec.periodInMs;
-        legacy_bucket_spec.max_period =
-            hidl_bucket_spec.exponentialMaxPeriodInMs;
+        legacy_bucket_spec.max_period = hidl_bucket_spec.exponentialMaxPeriodInMs;
         legacy_bucket_spec.base = hidl_bucket_spec.exponentialBase;
         legacy_bucket_spec.step_count = hidl_bucket_spec.exponentialStepCount;
         legacy_bucket_spec.report_events = 0;
         using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask;
-        for (const auto flag : {HidlFlag::EACH_SCAN, HidlFlag::FULL_RESULTS,
-                                HidlFlag::NO_BATCH}) {
+        for (const auto flag : {HidlFlag::EACH_SCAN, HidlFlag::FULL_RESULTS, HidlFlag::NO_BATCH}) {
             if (hidl_bucket_spec.eventReportScheme &
                 static_cast<std::underlying_type<HidlFlag>::type>(flag)) {
-                legacy_bucket_spec.report_events |=
-                    convertHidlGscanReportEventFlagToLegacy(flag);
+                legacy_bucket_spec.report_events |= convertHidlGscanReportEventFlagToLegacy(flag);
             }
         }
         if (hidl_bucket_spec.frequencies.size() > MAX_CHANNELS) {
             return false;
         }
         legacy_bucket_spec.num_channels = hidl_bucket_spec.frequencies.size();
-        for (uint32_t freq_idx = 0;
-             freq_idx < hidl_bucket_spec.frequencies.size(); freq_idx++) {
-            legacy_bucket_spec.channels[freq_idx].channel =
-                hidl_bucket_spec.frequencies[freq_idx];
+        for (uint32_t freq_idx = 0; freq_idx < hidl_bucket_spec.frequencies.size(); freq_idx++) {
+            legacy_bucket_spec.channels[freq_idx].channel = hidl_bucket_spec.frequencies[freq_idx];
         }
     }
     return true;
 }
 
-bool convertLegacyIeToHidl(
-    const legacy_hal::wifi_information_element& legacy_ie,
-    WifiInformationElement* hidl_ie) {
+bool convertLegacyIeToHidl(const legacy_hal::wifi_information_element& legacy_ie,
+                           WifiInformationElement* hidl_ie) {
     if (!hidl_ie) {
         return false;
     }
     *hidl_ie = {};
     hidl_ie->id = legacy_ie.id;
-    hidl_ie->data =
-        std::vector<uint8_t>(legacy_ie.data, legacy_ie.data + legacy_ie.len);
+    hidl_ie->data = std::vector<uint8_t>(legacy_ie.data, legacy_ie.data + legacy_ie.len);
     return true;
 }
 
@@ -702,14 +659,12 @@
         uint32_t curr_ie_len = kIeHeaderLen + legacy_ie.len;
         if (next_ie + curr_ie_len > ies_end) {
             LOG(ERROR) << "Error parsing IE blob. Next IE: " << (void*)next_ie
-                       << ", Curr IE len: " << curr_ie_len
-                       << ", IEs End: " << (void*)ies_end;
+                       << ", Curr IE len: " << curr_ie_len << ", IEs End: " << (void*)ies_end;
             break;
         }
         WifiInformationElement hidl_ie;
         if (!convertLegacyIeToHidl(legacy_ie, &hidl_ie)) {
-            LOG(ERROR) << "Error converting IE. Id: " << legacy_ie.id
-                       << ", len: " << legacy_ie.len;
+            LOG(ERROR) << "Error converting IE. Id: " << legacy_ie.id << ", len: " << legacy_ie.len;
             break;
         }
         hidl_ies->push_back(std::move(hidl_ie));
@@ -717,24 +672,23 @@
     }
     // Check if the blob has been fully consumed.
     if (next_ie != ies_end) {
-        LOG(ERROR) << "Failed to fully parse IE blob. Next IE: "
-                   << (void*)next_ie << ", IEs End: " << (void*)ies_end;
+        LOG(ERROR) << "Failed to fully parse IE blob. Next IE: " << (void*)next_ie
+                   << ", IEs End: " << (void*)ies_end;
     }
     return true;
 }
 
-bool convertLegacyGscanResultToHidl(
-    const legacy_hal::wifi_scan_result& legacy_scan_result, bool has_ie_data,
-    StaScanResult* hidl_scan_result) {
+bool convertLegacyGscanResultToHidl(const legacy_hal::wifi_scan_result& legacy_scan_result,
+                                    bool has_ie_data, StaScanResult* hidl_scan_result) {
     if (!hidl_scan_result) {
         return false;
     }
     *hidl_scan_result = {};
     hidl_scan_result->timeStampInUs = legacy_scan_result.ts;
     hidl_scan_result->ssid = std::vector<uint8_t>(
-        legacy_scan_result.ssid,
-        legacy_scan_result.ssid + strnlen(legacy_scan_result.ssid,
-                                          sizeof(legacy_scan_result.ssid) - 1));
+            legacy_scan_result.ssid,
+            legacy_scan_result.ssid +
+                    strnlen(legacy_scan_result.ssid, sizeof(legacy_scan_result.ssid) - 1));
     memcpy(hidl_scan_result->bssid.data(), legacy_scan_result.bssid,
            hidl_scan_result->bssid.size());
     hidl_scan_result->frequency = legacy_scan_result.channel;
@@ -743,9 +697,8 @@
     hidl_scan_result->capability = legacy_scan_result.capability;
     if (has_ie_data) {
         std::vector<WifiInformationElement> ies;
-        if (!convertLegacyIeBlobToHidl(
-                reinterpret_cast<const uint8_t*>(legacy_scan_result.ie_data),
-                legacy_scan_result.ie_length, &ies)) {
+        if (!convertLegacyIeBlobToHidl(reinterpret_cast<const uint8_t*>(legacy_scan_result.ie_data),
+                                       legacy_scan_result.ie_length, &ies)) {
             return false;
         }
         hidl_scan_result->informationElements = std::move(ies);
@@ -754,8 +707,8 @@
 }
 
 bool convertLegacyCachedGscanResultsToHidl(
-    const legacy_hal::wifi_cached_scan_results& legacy_cached_scan_result,
-    StaScanData* hidl_scan_data) {
+        const legacy_hal::wifi_cached_scan_results& legacy_cached_scan_result,
+        StaScanData* hidl_scan_data) {
     if (!hidl_scan_data) {
         return false;
     }
@@ -763,8 +716,7 @@
     hidl_scan_data->flags = 0;
     for (const auto flag : {legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED}) {
         if (legacy_cached_scan_result.flags & flag) {
-            hidl_scan_data->flags |=
-                static_cast<std::underlying_type<StaScanDataFlagMask>::type>(
+            hidl_scan_data->flags |= static_cast<std::underlying_type<StaScanDataFlagMask>::type>(
                     convertLegacyGscanDataFlagToHidl(flag));
         }
     }
@@ -773,12 +725,10 @@
     CHECK(legacy_cached_scan_result.num_results >= 0 &&
           legacy_cached_scan_result.num_results <= MAX_AP_CACHE_PER_SCAN);
     std::vector<StaScanResult> hidl_scan_results;
-    for (int32_t result_idx = 0;
-         result_idx < legacy_cached_scan_result.num_results; result_idx++) {
+    for (int32_t result_idx = 0; result_idx < legacy_cached_scan_result.num_results; result_idx++) {
         StaScanResult hidl_scan_result;
-        if (!convertLegacyGscanResultToHidl(
-                legacy_cached_scan_result.results[result_idx], false,
-                &hidl_scan_result)) {
+        if (!convertLegacyGscanResultToHidl(legacy_cached_scan_result.results[result_idx], false,
+                                            &hidl_scan_result)) {
             return false;
         }
         hidl_scan_results.push_back(hidl_scan_result);
@@ -788,17 +738,15 @@
 }
 
 bool convertLegacyVectorOfCachedGscanResultsToHidl(
-    const std::vector<legacy_hal::wifi_cached_scan_results>&
-        legacy_cached_scan_results,
-    std::vector<StaScanData>* hidl_scan_datas) {
+        const std::vector<legacy_hal::wifi_cached_scan_results>& legacy_cached_scan_results,
+        std::vector<StaScanData>* hidl_scan_datas) {
     if (!hidl_scan_datas) {
         return false;
     }
     *hidl_scan_datas = {};
     for (const auto& legacy_cached_scan_result : legacy_cached_scan_results) {
         StaScanData hidl_scan_data;
-        if (!convertLegacyCachedGscanResultsToHidl(legacy_cached_scan_result,
-                                                   &hidl_scan_data)) {
+        if (!convertLegacyCachedGscanResultsToHidl(legacy_cached_scan_result, &hidl_scan_data)) {
             return false;
         }
         hidl_scan_datas->push_back(hidl_scan_data);
@@ -806,8 +754,7 @@
     return true;
 }
 
-WifiDebugTxPacketFate convertLegacyDebugTxPacketFateToHidl(
-    legacy_hal::wifi_tx_packet_fate fate) {
+WifiDebugTxPacketFate convertLegacyDebugTxPacketFateToHidl(legacy_hal::wifi_tx_packet_fate fate) {
     switch (fate) {
         case legacy_hal::TX_PKT_FATE_ACKED:
             return WifiDebugTxPacketFate::ACKED;
@@ -833,8 +780,7 @@
     CHECK(false) << "Unknown legacy fate type: " << fate;
 }
 
-WifiDebugRxPacketFate convertLegacyDebugRxPacketFateToHidl(
-    legacy_hal::wifi_rx_packet_fate fate) {
+WifiDebugRxPacketFate convertLegacyDebugRxPacketFateToHidl(legacy_hal::wifi_rx_packet_fate fate) {
     switch (fate) {
         case legacy_hal::RX_PKT_FATE_SUCCESS:
             return WifiDebugRxPacketFate::SUCCESS;
@@ -863,7 +809,7 @@
 }
 
 WifiDebugPacketFateFrameType convertLegacyDebugPacketFateFrameTypeToHidl(
-    legacy_hal::frame_type type) {
+        legacy_hal::frame_type type) {
     switch (type) {
         case legacy_hal::FRAME_TYPE_UNKNOWN:
             return WifiDebugPacketFateFrameType::UNKNOWN;
@@ -875,40 +821,36 @@
     CHECK(false) << "Unknown legacy frame type: " << type;
 }
 
-bool convertLegacyDebugPacketFateFrameToHidl(
-    const legacy_hal::frame_info& legacy_frame,
-    WifiDebugPacketFateFrameInfo* hidl_frame) {
+bool convertLegacyDebugPacketFateFrameToHidl(const legacy_hal::frame_info& legacy_frame,
+                                             WifiDebugPacketFateFrameInfo* hidl_frame) {
     if (!hidl_frame) {
         return false;
     }
     *hidl_frame = {};
-    hidl_frame->frameType =
-        convertLegacyDebugPacketFateFrameTypeToHidl(legacy_frame.payload_type);
+    hidl_frame->frameType = convertLegacyDebugPacketFateFrameTypeToHidl(legacy_frame.payload_type);
     hidl_frame->frameLen = legacy_frame.frame_len;
     hidl_frame->driverTimestampUsec = legacy_frame.driver_timestamp_usec;
     hidl_frame->firmwareTimestampUsec = legacy_frame.firmware_timestamp_usec;
-    const uint8_t* frame_begin = reinterpret_cast<const uint8_t*>(
-        legacy_frame.frame_content.ethernet_ii_bytes);
+    const uint8_t* frame_begin =
+            reinterpret_cast<const uint8_t*>(legacy_frame.frame_content.ethernet_ii_bytes);
     hidl_frame->frameContent =
-        std::vector<uint8_t>(frame_begin, frame_begin + legacy_frame.frame_len);
+            std::vector<uint8_t>(frame_begin, frame_begin + legacy_frame.frame_len);
     return true;
 }
 
-bool convertLegacyDebugTxPacketFateToHidl(
-    const legacy_hal::wifi_tx_report& legacy_fate,
-    WifiDebugTxPacketFateReport* hidl_fate) {
+bool convertLegacyDebugTxPacketFateToHidl(const legacy_hal::wifi_tx_report& legacy_fate,
+                                          WifiDebugTxPacketFateReport* hidl_fate) {
     if (!hidl_fate) {
         return false;
     }
     *hidl_fate = {};
     hidl_fate->fate = convertLegacyDebugTxPacketFateToHidl(legacy_fate.fate);
-    return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf,
-                                                   &hidl_fate->frameInfo);
+    return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf, &hidl_fate->frameInfo);
 }
 
 bool convertLegacyVectorOfDebugTxPacketFateToHidl(
-    const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
-    std::vector<WifiDebugTxPacketFateReport>* hidl_fates) {
+        const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
+        std::vector<WifiDebugTxPacketFateReport>* hidl_fates) {
     if (!hidl_fates) {
         return false;
     }
@@ -923,21 +865,19 @@
     return true;
 }
 
-bool convertLegacyDebugRxPacketFateToHidl(
-    const legacy_hal::wifi_rx_report& legacy_fate,
-    WifiDebugRxPacketFateReport* hidl_fate) {
+bool convertLegacyDebugRxPacketFateToHidl(const legacy_hal::wifi_rx_report& legacy_fate,
+                                          WifiDebugRxPacketFateReport* hidl_fate) {
     if (!hidl_fate) {
         return false;
     }
     *hidl_fate = {};
     hidl_fate->fate = convertLegacyDebugRxPacketFateToHidl(legacy_fate.fate);
-    return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf,
-                                                   &hidl_fate->frameInfo);
+    return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf, &hidl_fate->frameInfo);
 }
 
 bool convertLegacyVectorOfDebugRxPacketFateToHidl(
-    const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
-    std::vector<WifiDebugRxPacketFateReport>* hidl_fates) {
+        const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
+        std::vector<WifiDebugRxPacketFateReport>* hidl_fates) {
     if (!hidl_fates) {
         return false;
     }
@@ -953,8 +893,8 @@
 }
 
 bool convertLegacyLinkLayerRadioStatsToHidl(
-    const legacy_hal::LinkLayerRadioStats& legacy_radio_stat,
-    V1_5::StaLinkLayerRadioStats* hidl_radio_stat) {
+        const legacy_hal::LinkLayerRadioStats& legacy_radio_stat,
+        V1_5::StaLinkLayerRadioStats* hidl_radio_stat) {
     if (!hidl_radio_stat) {
         return false;
     }
@@ -964,20 +904,13 @@
     hidl_radio_stat->V1_3.V1_0.onTimeInMs = legacy_radio_stat.stats.on_time;
     hidl_radio_stat->V1_3.V1_0.txTimeInMs = legacy_radio_stat.stats.tx_time;
     hidl_radio_stat->V1_3.V1_0.rxTimeInMs = legacy_radio_stat.stats.rx_time;
-    hidl_radio_stat->V1_3.V1_0.onTimeInMsForScan =
-        legacy_radio_stat.stats.on_time_scan;
-    hidl_radio_stat->V1_3.V1_0.txTimeInMsPerLevel =
-        legacy_radio_stat.tx_time_per_levels;
-    hidl_radio_stat->V1_3.onTimeInMsForNanScan =
-        legacy_radio_stat.stats.on_time_nbd;
-    hidl_radio_stat->V1_3.onTimeInMsForBgScan =
-        legacy_radio_stat.stats.on_time_gscan;
-    hidl_radio_stat->V1_3.onTimeInMsForRoamScan =
-        legacy_radio_stat.stats.on_time_roam_scan;
-    hidl_radio_stat->V1_3.onTimeInMsForPnoScan =
-        legacy_radio_stat.stats.on_time_pno_scan;
-    hidl_radio_stat->V1_3.onTimeInMsForHs20Scan =
-        legacy_radio_stat.stats.on_time_hs20;
+    hidl_radio_stat->V1_3.V1_0.onTimeInMsForScan = legacy_radio_stat.stats.on_time_scan;
+    hidl_radio_stat->V1_3.V1_0.txTimeInMsPerLevel = legacy_radio_stat.tx_time_per_levels;
+    hidl_radio_stat->V1_3.onTimeInMsForNanScan = legacy_radio_stat.stats.on_time_nbd;
+    hidl_radio_stat->V1_3.onTimeInMsForBgScan = legacy_radio_stat.stats.on_time_gscan;
+    hidl_radio_stat->V1_3.onTimeInMsForRoamScan = legacy_radio_stat.stats.on_time_roam_scan;
+    hidl_radio_stat->V1_3.onTimeInMsForPnoScan = legacy_radio_stat.stats.on_time_pno_scan;
+    hidl_radio_stat->V1_3.onTimeInMsForHs20Scan = legacy_radio_stat.stats.on_time_hs20;
 
     std::vector<V1_3::WifiChannelStats> hidl_channel_stats;
 
@@ -991,10 +924,8 @@
          */
         hidl_channel_stat.channel.width = WifiChannelWidthInMhz::WIDTH_20;
         hidl_channel_stat.channel.centerFreq = channel_stat.channel.center_freq;
-        hidl_channel_stat.channel.centerFreq0 =
-            channel_stat.channel.center_freq0;
-        hidl_channel_stat.channel.centerFreq1 =
-            channel_stat.channel.center_freq1;
+        hidl_channel_stat.channel.centerFreq0 = channel_stat.channel.center_freq0;
+        hidl_channel_stat.channel.centerFreq1 = channel_stat.channel.center_freq1;
         hidl_channel_stats.push_back(hidl_channel_stat);
     }
 
@@ -1003,9 +934,8 @@
     return true;
 }
 
-bool convertLegacyLinkLayerStatsToHidl(
-    const legacy_hal::LinkLayerStats& legacy_stats,
-    StaLinkLayerStats* hidl_stats) {
+bool convertLegacyLinkLayerStatsToHidl(const legacy_hal::LinkLayerStats& legacy_stats,
+                                       V1_5::StaLinkLayerStats* hidl_stats) {
     if (!hidl_stats) {
         return false;
     }
@@ -1014,77 +944,76 @@
     hidl_stats->iface.V1_0.beaconRx = legacy_stats.iface.beacon_rx;
     hidl_stats->iface.V1_0.avgRssiMgmt = legacy_stats.iface.rssi_mgmt;
     hidl_stats->iface.V1_0.wmeBePktStats.rxMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu;
     hidl_stats->iface.V1_0.wmeBePktStats.txMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu;
     hidl_stats->iface.V1_0.wmeBePktStats.lostMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost;
     hidl_stats->iface.V1_0.wmeBePktStats.retries =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries;
     hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMinInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min;
     hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max;
     hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg;
     hidl_stats->iface.wmeBeContentionTimeStats.contentionNumSamples =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples;
     hidl_stats->iface.V1_0.wmeBkPktStats.rxMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu;
     hidl_stats->iface.V1_0.wmeBkPktStats.txMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu;
     hidl_stats->iface.V1_0.wmeBkPktStats.lostMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost;
     hidl_stats->iface.V1_0.wmeBkPktStats.retries =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries;
     hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMinInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min;
     hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max;
     hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg;
     hidl_stats->iface.wmeBkContentionTimeStats.contentionNumSamples =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples;
     hidl_stats->iface.V1_0.wmeViPktStats.rxMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu;
     hidl_stats->iface.V1_0.wmeViPktStats.txMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu;
     hidl_stats->iface.V1_0.wmeViPktStats.lostMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost;
     hidl_stats->iface.V1_0.wmeViPktStats.retries =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries;
     hidl_stats->iface.wmeViContentionTimeStats.contentionTimeMinInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min;
     hidl_stats->iface.wmeViContentionTimeStats.contentionTimeMaxInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max;
     hidl_stats->iface.wmeViContentionTimeStats.contentionTimeAvgInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg;
     hidl_stats->iface.wmeViContentionTimeStats.contentionNumSamples =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples;
     hidl_stats->iface.V1_0.wmeVoPktStats.rxMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu;
     hidl_stats->iface.V1_0.wmeVoPktStats.txMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu;
     hidl_stats->iface.V1_0.wmeVoPktStats.lostMpdu =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost;
     hidl_stats->iface.V1_0.wmeVoPktStats.retries =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
     hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMinInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min;
     hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max;
     hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg;
     hidl_stats->iface.wmeVoContentionTimeStats.contentionNumSamples =
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples;
+            legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples;
     hidl_stats->iface.timeSliceDutyCycleInPercent =
-        legacy_stats.iface.info.time_slicing_duty_cycle_percent;
+            legacy_stats.iface.info.time_slicing_duty_cycle_percent;
     // peer info legacy_stats conversion.
-    std::vector<StaPeerInfo> hidl_peers_info_stats;
+    std::vector<V1_5::StaPeerInfo> hidl_peers_info_stats;
     for (const auto& legacy_peer_info_stats : legacy_stats.peers) {
-        StaPeerInfo hidl_peer_info_stats;
-        if (!convertLegacyPeerInfoStatsToHidl(legacy_peer_info_stats,
-                                              &hidl_peer_info_stats)) {
+        V1_5::StaPeerInfo hidl_peer_info_stats;
+        if (!convertLegacyPeerInfoStatsToHidl(legacy_peer_info_stats, &hidl_peer_info_stats)) {
             return false;
         }
         hidl_peers_info_stats.push_back(hidl_peer_info_stats);
@@ -1094,8 +1023,7 @@
     std::vector<V1_5::StaLinkLayerRadioStats> hidl_radios_stats;
     for (const auto& legacy_radio_stats : legacy_stats.radios) {
         V1_5::StaLinkLayerRadioStats hidl_radio_stats;
-        if (!convertLegacyLinkLayerRadioStatsToHidl(legacy_radio_stats,
-                                                    &hidl_radio_stats)) {
+        if (!convertLegacyLinkLayerRadioStatsToHidl(legacy_radio_stats, &hidl_radio_stats)) {
             return false;
         }
         hidl_radios_stats.push_back(hidl_radio_stats);
@@ -1107,23 +1035,19 @@
     return true;
 }
 
-bool convertLegacyPeerInfoStatsToHidl(
-    const legacy_hal::WifiPeerInfo& legacy_peer_info_stats,
-    StaPeerInfo* hidl_peer_info_stats) {
+bool convertLegacyPeerInfoStatsToHidl(const legacy_hal::WifiPeerInfo& legacy_peer_info_stats,
+                                      V1_5::StaPeerInfo* hidl_peer_info_stats) {
     if (!hidl_peer_info_stats) {
         return false;
     }
     *hidl_peer_info_stats = {};
-    hidl_peer_info_stats->staCount =
-        legacy_peer_info_stats.peer_info.bssload.sta_count;
-    hidl_peer_info_stats->chanUtil =
-        legacy_peer_info_stats.peer_info.bssload.chan_util;
+    hidl_peer_info_stats->staCount = legacy_peer_info_stats.peer_info.bssload.sta_count;
+    hidl_peer_info_stats->chanUtil = legacy_peer_info_stats.peer_info.bssload.chan_util;
 
-    std::vector<StaRateStat> hidlRateStats;
+    std::vector<V1_5::StaRateStat> hidlRateStats;
     for (const auto& legacy_rate_stats : legacy_peer_info_stats.rate_stats) {
-        StaRateStat rateStat;
-        if (!convertLegacyWifiRateInfoToHidl(legacy_rate_stats.rate,
-                                             &rateStat.rateInfo)) {
+        V1_5::StaRateStat rateStat;
+        if (!convertLegacyWifiRateInfoToHidl(legacy_rate_stats.rate, &rateStat.rateInfo)) {
             return false;
         }
         rateStat.txMpdu = legacy_rate_stats.tx_mpdu;
@@ -1137,8 +1061,8 @@
 }
 
 bool convertLegacyRoamingCapabilitiesToHidl(
-    const legacy_hal::wifi_roaming_capabilities& legacy_caps,
-    StaRoamingCapabilities* hidl_caps) {
+        const legacy_hal::wifi_roaming_capabilities& legacy_caps,
+        StaRoamingCapabilities* hidl_caps) {
     if (!hidl_caps) {
         return false;
     }
@@ -1148,9 +1072,8 @@
     return true;
 }
 
-bool convertHidlRoamingConfigToLegacy(
-    const StaRoamingConfig& hidl_config,
-    legacy_hal::wifi_roaming_config* legacy_config) {
+bool convertHidlRoamingConfigToLegacy(const StaRoamingConfig& hidl_config,
+                                      legacy_hal::wifi_roaming_config* legacy_config) {
     if (!legacy_config) {
         return false;
     }
@@ -1170,15 +1093,13 @@
     for (const auto& ssid : hidl_config.ssidWhitelist) {
         CHECK(ssid.size() <= sizeof(legacy_hal::ssid_t::ssid_str));
         legacy_config->whitelist_ssid[i].length = ssid.size();
-        memcpy(legacy_config->whitelist_ssid[i].ssid_str, ssid.data(),
-               ssid.size());
+        memcpy(legacy_config->whitelist_ssid[i].ssid_str, ssid.data(), ssid.size());
         i++;
     }
     return true;
 }
 
-legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy(
-    StaRoamingState state) {
+legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy(StaRoamingState state) {
     switch (state) {
         case StaRoamingState::ENABLED:
             return legacy_hal::ROAMING_ENABLE;
@@ -1200,8 +1121,7 @@
     CHECK(false);
 }
 
-legacy_hal::NanPublishType convertHidlNanPublishTypeToLegacy(
-    NanPublishType type) {
+legacy_hal::NanPublishType convertHidlNanPublishTypeToLegacy(NanPublishType type) {
     switch (type) {
         case NanPublishType::UNSOLICITED:
             return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED;
@@ -1223,8 +1143,7 @@
     CHECK(false);
 }
 
-legacy_hal::NanSubscribeType convertHidlNanSubscribeTypeToLegacy(
-    NanSubscribeType type) {
+legacy_hal::NanSubscribeType convertHidlNanSubscribeTypeToLegacy(NanSubscribeType type) {
     switch (type) {
         case NanSubscribeType::PASSIVE:
             return legacy_hal::NAN_SUBSCRIBE_TYPE_PASSIVE;
@@ -1245,7 +1164,7 @@
 }
 
 legacy_hal::NanDataPathChannelCfg convertHidlNanDataPathChannelCfgToLegacy(
-    NanDataPathChannelCfg type) {
+        NanDataPathChannelCfg type) {
     switch (type) {
         case NanDataPathChannelCfg::CHANNEL_NOT_REQUESTED:
             return legacy_hal::NAN_DP_CHANNEL_NOT_REQUESTED;
@@ -1289,39 +1208,36 @@
     CHECK(false);
 }
 
-void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str,
-                            size_t max_len, WifiNanStatus* wifiNanStatus) {
+void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len,
+                            WifiNanStatus* wifiNanStatus) {
     wifiNanStatus->status = convertLegacyNanStatusTypeToHidl(type);
     wifiNanStatus->description = safeConvertChar(str, max_len);
 }
 
-bool convertHidlNanEnableRequestToLegacy(
-    const V1_4::NanEnableRequest& hidl_request,
-    legacy_hal::NanEnableRequest* legacy_request) {
+bool convertHidlNanEnableRequestToLegacy(const V1_4::NanEnableRequest& hidl_request,
+                                         legacy_hal::NanEnableRequest* legacy_request) {
     if (!legacy_request) {
-        LOG(ERROR)
-            << "convertHidlNanEnableRequestToLegacy: null legacy_request";
+        LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: null legacy_request";
         return false;
     }
     *legacy_request = {};
 
     legacy_request->config_2dot4g_support = 1;
     legacy_request->support_2dot4g_val =
-        hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+            hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_24GHZ];
     legacy_request->config_support_5g = 1;
     legacy_request->support_5g_val =
-        hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+            hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_5GHZ];
     legacy_request->config_hop_count_limit = 1;
     legacy_request->hop_count_limit_val = hidl_request.hopCountMax;
     legacy_request->master_pref = hidl_request.configParams.masterPref;
     legacy_request->discovery_indication_cfg = 0;
     legacy_request->discovery_indication_cfg |=
-        hidl_request.configParams.disableDiscoveryAddressChangeIndication ? 0x1
-                                                                          : 0x0;
+            hidl_request.configParams.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0;
     legacy_request->discovery_indication_cfg |=
-        hidl_request.configParams.disableStartedClusterIndication ? 0x2 : 0x0;
+            hidl_request.configParams.disableStartedClusterIndication ? 0x2 : 0x0;
     legacy_request->discovery_indication_cfg |=
-        hidl_request.configParams.disableJoinedClusterIndication ? 0x4 : 0x0;
+            hidl_request.configParams.disableJoinedClusterIndication ? 0x4 : 0x0;
     legacy_request->config_sid_beacon = 1;
     if (hidl_request.configParams.numberOfPublishServiceIdsInBeacon > 127) {
         LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: "
@@ -1329,9 +1245,8 @@
         return false;
     }
     legacy_request->sid_beacon_val =
-        (hidl_request.configParams.includePublishServiceIdsInBeacon ? 0x1
-                                                                    : 0x0) |
-        (hidl_request.configParams.numberOfPublishServiceIdsInBeacon << 1);
+            (hidl_request.configParams.includePublishServiceIdsInBeacon ? 0x1 : 0x0) |
+            (hidl_request.configParams.numberOfPublishServiceIdsInBeacon << 1);
     legacy_request->config_subscribe_sid_beacon = 1;
     if (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon > 127) {
         LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: "
@@ -1339,15 +1254,13 @@
         return false;
     }
     legacy_request->subscribe_sid_beacon_val =
-        (hidl_request.configParams.includeSubscribeServiceIdsInBeacon ? 0x1
-                                                                      : 0x0) |
-        (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon << 1);
+            (hidl_request.configParams.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) |
+            (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon << 1);
     legacy_request->config_rssi_window_size = 1;
-    legacy_request->rssi_window_size_val =
-        hidl_request.configParams.rssiWindowSize;
+    legacy_request->rssi_window_size_val = hidl_request.configParams.rssiWindowSize;
     legacy_request->config_disc_mac_addr_randomization = 1;
     legacy_request->disc_mac_addr_rand_interval_sec =
-        hidl_request.configParams.macAddressRandomizationIntervalSec;
+            hidl_request.configParams.macAddressRandomizationIntervalSec;
     legacy_request->config_2dot4g_rssi_close = 1;
     if (hidl_request.configParams.bandSpecificConfig.size() != 3) {
         LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: "
@@ -1355,134 +1268,93 @@
         return false;
     }
     legacy_request->rssi_close_2dot4g_val =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
-            .rssiClose;
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+                    .rssiClose;
     legacy_request->config_2dot4g_rssi_middle = 1;
     legacy_request->rssi_middle_2dot4g_val =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
-            .rssiMiddle;
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+                    .rssiMiddle;
     legacy_request->config_2dot4g_rssi_proximity = 1;
     legacy_request->rssi_proximity_2dot4g_val =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
-            .rssiCloseProximity;
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+                    .rssiCloseProximity;
     legacy_request->config_scan_params = 1;
-    legacy_request->scan_params_val
-        .dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
-            .dwellTimeMs;
-    legacy_request->scan_params_val
-        .scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
-            .scanPeriodSec;
+    legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+                    .dwellTimeMs;
+    legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+                    .scanPeriodSec;
     legacy_request->config_dw.config_2dot4g_dw_band =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
-            .validDiscoveryWindowIntervalVal;
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+                    .validDiscoveryWindowIntervalVal;
     legacy_request->config_dw.dw_2dot4g_interval_val =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
-            .discoveryWindowIntervalVal;
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+                    .discoveryWindowIntervalVal;
     legacy_request->config_5g_rssi_close = 1;
     legacy_request->rssi_close_5g_val =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .rssiClose;
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+                    .rssiClose;
     legacy_request->config_5g_rssi_middle = 1;
     legacy_request->rssi_middle_5g_val =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .rssiMiddle;
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+                    .rssiMiddle;
     legacy_request->config_5g_rssi_close_proximity = 1;
     legacy_request->rssi_close_proximity_5g_val =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .rssiCloseProximity;
-    legacy_request->scan_params_val
-        .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .dwellTimeMs;
-    legacy_request->scan_params_val
-        .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .scanPeriodSec;
-    legacy_request->scan_params_val
-        .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .dwellTimeMs;
-    legacy_request->scan_params_val
-        .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .scanPeriodSec;
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+                    .rssiCloseProximity;
+    legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+                    .dwellTimeMs;
+    legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+                    .scanPeriodSec;
+    legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+                    .dwellTimeMs;
+    legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+                    .scanPeriodSec;
     legacy_request->config_dw.config_5g_dw_band =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .validDiscoveryWindowIntervalVal;
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+                    .validDiscoveryWindowIntervalVal;
     legacy_request->config_dw.dw_5g_interval_val =
-        hidl_request.configParams
-            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .discoveryWindowIntervalVal;
+            hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+                    .discoveryWindowIntervalVal;
     if (hidl_request.debugConfigs.validClusterIdVals) {
-        legacy_request->cluster_low =
-            hidl_request.debugConfigs.clusterIdBottomRangeVal;
-        legacy_request->cluster_high =
-            hidl_request.debugConfigs.clusterIdTopRangeVal;
+        legacy_request->cluster_low = hidl_request.debugConfigs.clusterIdBottomRangeVal;
+        legacy_request->cluster_high = hidl_request.debugConfigs.clusterIdTopRangeVal;
     } else {  // need 'else' since not configurable in legacy HAL
         legacy_request->cluster_low = 0x0000;
         legacy_request->cluster_high = 0xFFFF;
     }
-    legacy_request->config_intf_addr =
-        hidl_request.debugConfigs.validIntfAddrVal;
-    memcpy(legacy_request->intf_addr_val,
-           hidl_request.debugConfigs.intfAddrVal.data(), 6);
+    legacy_request->config_intf_addr = hidl_request.debugConfigs.validIntfAddrVal;
+    memcpy(legacy_request->intf_addr_val, hidl_request.debugConfigs.intfAddrVal.data(), 6);
     legacy_request->config_oui = hidl_request.debugConfigs.validOuiVal;
     legacy_request->oui_val = hidl_request.debugConfigs.ouiVal;
     legacy_request->config_random_factor_force =
-        hidl_request.debugConfigs.validRandomFactorForceVal;
-    legacy_request->random_factor_force_val =
-        hidl_request.debugConfigs.randomFactorForceVal;
-    legacy_request->config_hop_count_force =
-        hidl_request.debugConfigs.validHopCountForceVal;
-    legacy_request->hop_count_force_val =
-        hidl_request.debugConfigs.hopCountForceVal;
-    legacy_request->config_24g_channel =
-        hidl_request.debugConfigs.validDiscoveryChannelVal;
+            hidl_request.debugConfigs.validRandomFactorForceVal;
+    legacy_request->random_factor_force_val = hidl_request.debugConfigs.randomFactorForceVal;
+    legacy_request->config_hop_count_force = hidl_request.debugConfigs.validHopCountForceVal;
+    legacy_request->hop_count_force_val = hidl_request.debugConfigs.hopCountForceVal;
+    legacy_request->config_24g_channel = hidl_request.debugConfigs.validDiscoveryChannelVal;
     legacy_request->channel_24g_val =
-        hidl_request.debugConfigs
-            .discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
-    legacy_request->config_5g_channel =
-        hidl_request.debugConfigs.validDiscoveryChannelVal;
+            hidl_request.debugConfigs.discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+    legacy_request->config_5g_channel = hidl_request.debugConfigs.validDiscoveryChannelVal;
     legacy_request->channel_5g_val =
-        hidl_request.debugConfigs
-            .discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
-    legacy_request->config_2dot4g_beacons =
-        hidl_request.debugConfigs.validUseBeaconsInBandVal;
+            hidl_request.debugConfigs.discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+    legacy_request->config_2dot4g_beacons = hidl_request.debugConfigs.validUseBeaconsInBandVal;
     legacy_request->beacon_2dot4g_val =
-        hidl_request.debugConfigs
-            .useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
-    legacy_request->config_5g_beacons =
-        hidl_request.debugConfigs.validUseBeaconsInBandVal;
+            hidl_request.debugConfigs.useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+    legacy_request->config_5g_beacons = hidl_request.debugConfigs.validUseBeaconsInBandVal;
     legacy_request->beacon_5g_val =
-        hidl_request.debugConfigs
-            .useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
-    legacy_request->config_2dot4g_sdf =
-        hidl_request.debugConfigs.validUseSdfInBandVal;
+            hidl_request.debugConfigs.useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+    legacy_request->config_2dot4g_sdf = hidl_request.debugConfigs.validUseSdfInBandVal;
     legacy_request->sdf_2dot4g_val =
-        hidl_request.debugConfigs
-            .useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
-    legacy_request->config_5g_sdf =
-        hidl_request.debugConfigs.validUseSdfInBandVal;
+            hidl_request.debugConfigs.useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+    legacy_request->config_5g_sdf = hidl_request.debugConfigs.validUseSdfInBandVal;
     legacy_request->sdf_5g_val =
-        hidl_request.debugConfigs
-            .useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+            hidl_request.debugConfigs.useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
 
     /* TODO: b/145609058
      * Missing updates needed to legacy_hal::NanEnableRequest and conversion to
@@ -1491,13 +1363,11 @@
     return true;
 }
 
-bool convertHidlNanEnableRequest_1_4ToLegacy(
-    const V1_4::NanEnableRequest& hidl_request1,
-    const NanConfigRequestSupplemental& hidl_request2,
-    legacy_hal::NanEnableRequest* legacy_request) {
+bool convertHidlNanEnableRequest_1_4ToLegacy(const V1_4::NanEnableRequest& hidl_request1,
+                                             const NanConfigRequestSupplemental& hidl_request2,
+                                             legacy_hal::NanEnableRequest* legacy_request) {
     if (!legacy_request) {
-        LOG(ERROR)
-            << "convertHidlNanEnableRequest_1_4ToLegacy: null legacy_request";
+        LOG(ERROR) << "convertHidlNanEnableRequest_1_4ToLegacy: null legacy_request";
         return false;
     }
 
@@ -1507,71 +1377,60 @@
     }
 
     legacy_request->config_discovery_beacon_int = 1;
-    legacy_request->discovery_beacon_interval =
-        hidl_request2.V1_2.discoveryBeaconIntervalMs;
+    legacy_request->discovery_beacon_interval = hidl_request2.V1_2.discoveryBeaconIntervalMs;
     legacy_request->config_nss = 1;
     legacy_request->nss = hidl_request2.V1_2.numberOfSpatialStreamsInDiscovery;
     legacy_request->config_dw_early_termination = 1;
     legacy_request->enable_dw_termination =
-        hidl_request2.V1_2.enableDiscoveryWindowEarlyTermination;
+            hidl_request2.V1_2.enableDiscoveryWindowEarlyTermination;
     legacy_request->config_enable_ranging = 1;
     legacy_request->enable_ranging = hidl_request2.V1_2.enableRanging;
 
     return true;
 }
 
-bool convertHidlNanEnableRequest_1_5ToLegacy(
-    const V1_4::NanEnableRequest& hidl_request1,
-    const NanConfigRequestSupplemental& hidl_request2,
-    legacy_hal::NanEnableRequest* legacy_request) {
+bool convertHidlNanEnableRequest_1_5ToLegacy(const V1_4::NanEnableRequest& hidl_request1,
+                                             const NanConfigRequestSupplemental& hidl_request2,
+                                             legacy_hal::NanEnableRequest* legacy_request) {
     if (!legacy_request) {
-        LOG(ERROR)
-            << "convertHidlNanEnableRequest_1_5ToLegacy: null legacy_request";
+        LOG(ERROR) << "convertHidlNanEnableRequest_1_5ToLegacy: null legacy_request";
         return false;
     }
 
     *legacy_request = {};
-    if (!convertHidlNanEnableRequest_1_4ToLegacy(hidl_request1, hidl_request2,
-                                                 legacy_request)) {
+    if (!convertHidlNanEnableRequest_1_4ToLegacy(hidl_request1, hidl_request2, legacy_request)) {
         return false;
     }
 
     legacy_request->config_enable_instant_mode = 1;
-    legacy_request->enable_instant_mode =
-        hidl_request2.enableInstantCommunicationMode;
+    legacy_request->enable_instant_mode = hidl_request2.enableInstantCommunicationMode;
 
     return true;
 }
 
-bool convertHidlNanConfigRequest_1_5ToLegacy(
-    const V1_4::NanConfigRequest& hidl_request1,
-    const NanConfigRequestSupplemental& hidl_request2,
-    legacy_hal::NanConfigRequest* legacy_request) {
+bool convertHidlNanConfigRequest_1_5ToLegacy(const V1_4::NanConfigRequest& hidl_request1,
+                                             const NanConfigRequestSupplemental& hidl_request2,
+                                             legacy_hal::NanConfigRequest* legacy_request) {
     if (!legacy_request) {
-        LOG(ERROR)
-            << "convertHidlNanConfigRequest_1_5ToLegacy: null legacy_request";
+        LOG(ERROR) << "convertHidlNanConfigRequest_1_5ToLegacy: null legacy_request";
         return false;
     }
 
     *legacy_request = {};
-    if (!convertHidlNanConfigRequest_1_4ToLegacy(hidl_request1, hidl_request2,
-                                                 legacy_request)) {
+    if (!convertHidlNanConfigRequest_1_4ToLegacy(hidl_request1, hidl_request2, legacy_request)) {
         return false;
     }
 
     legacy_request->config_enable_instant_mode = 1;
-    legacy_request->enable_instant_mode =
-        hidl_request2.enableInstantCommunicationMode;
+    legacy_request->enable_instant_mode = hidl_request2.enableInstantCommunicationMode;
 
     return true;
 }
 
-bool convertHidlNanPublishRequestToLegacy(
-    const NanPublishRequest& hidl_request,
-    legacy_hal::NanPublishRequest* legacy_request) {
+bool convertHidlNanPublishRequestToLegacy(const NanPublishRequest& hidl_request,
+                                          legacy_hal::NanPublishRequest* legacy_request) {
     if (!legacy_request) {
-        LOG(ERROR)
-            << "convertHidlNanPublishRequestToLegacy: null legacy_request";
+        LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: null legacy_request";
         return false;
     }
     *legacy_request = {};
@@ -1580,22 +1439,18 @@
     legacy_request->ttl = hidl_request.baseConfigs.ttlSec;
     legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod;
     legacy_request->publish_count = hidl_request.baseConfigs.discoveryCount;
-    legacy_request->service_name_len =
-        hidl_request.baseConfigs.serviceName.size();
+    legacy_request->service_name_len = hidl_request.baseConfigs.serviceName.size();
     if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
         LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: service_name_len "
                       "too large";
         return false;
     }
-    memcpy(legacy_request->service_name,
-           hidl_request.baseConfigs.serviceName.data(),
+    memcpy(legacy_request->service_name, hidl_request.baseConfigs.serviceName.data(),
            legacy_request->service_name_len);
-    legacy_request->publish_match_indicator = convertHidlNanMatchAlgToLegacy(
-        hidl_request.baseConfigs.discoveryMatchIndicator);
-    legacy_request->service_specific_info_len =
-        hidl_request.baseConfigs.serviceSpecificInfo.size();
-    if (legacy_request->service_specific_info_len >
-        NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+    legacy_request->publish_match_indicator =
+            convertHidlNanMatchAlgToLegacy(hidl_request.baseConfigs.discoveryMatchIndicator);
+    legacy_request->service_specific_info_len = hidl_request.baseConfigs.serviceSpecificInfo.size();
+    if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
         LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
                       "service_specific_info_len too large";
         return false;
@@ -1604,9 +1459,8 @@
            hidl_request.baseConfigs.serviceSpecificInfo.data(),
            legacy_request->service_specific_info_len);
     legacy_request->sdea_service_specific_info_len =
-        hidl_request.baseConfigs.extendedServiceSpecificInfo.size();
-    if (legacy_request->sdea_service_specific_info_len >
-        NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+            hidl_request.baseConfigs.extendedServiceSpecificInfo.size();
+    if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
         LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
                       "sdea_service_specific_info_len too large";
         return false;
@@ -1614,49 +1468,38 @@
     memcpy(legacy_request->sdea_service_specific_info,
            hidl_request.baseConfigs.extendedServiceSpecificInfo.data(),
            legacy_request->sdea_service_specific_info_len);
-    legacy_request->rx_match_filter_len =
-        hidl_request.baseConfigs.rxMatchFilter.size();
+    legacy_request->rx_match_filter_len = hidl_request.baseConfigs.rxMatchFilter.size();
     if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
         LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
                       "rx_match_filter_len too large";
         return false;
     }
-    memcpy(legacy_request->rx_match_filter,
-           hidl_request.baseConfigs.rxMatchFilter.data(),
+    memcpy(legacy_request->rx_match_filter, hidl_request.baseConfigs.rxMatchFilter.data(),
            legacy_request->rx_match_filter_len);
-    legacy_request->tx_match_filter_len =
-        hidl_request.baseConfigs.txMatchFilter.size();
+    legacy_request->tx_match_filter_len = hidl_request.baseConfigs.txMatchFilter.size();
     if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
         LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
                       "tx_match_filter_len too large";
         return false;
     }
-    memcpy(legacy_request->tx_match_filter,
-           hidl_request.baseConfigs.txMatchFilter.data(),
+    memcpy(legacy_request->tx_match_filter, hidl_request.baseConfigs.txMatchFilter.data(),
            legacy_request->tx_match_filter_len);
-    legacy_request->rssi_threshold_flag =
-        hidl_request.baseConfigs.useRssiThreshold;
+    legacy_request->rssi_threshold_flag = hidl_request.baseConfigs.useRssiThreshold;
     legacy_request->recv_indication_cfg = 0;
     legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1
-                                                                       : 0x0;
+            hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0;
     legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
+            hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
     legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
+            hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
     legacy_request->recv_indication_cfg |= 0x8;
-    legacy_request->cipher_type =
-        (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType;
-    if (hidl_request.baseConfigs.securityConfig.securityType ==
-        NanDataPathSecurityType::PMK) {
-        legacy_request->key_info.key_type =
-            legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+    legacy_request->cipher_type = (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType;
+    if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
         legacy_request->key_info.body.pmk_info.pmk_len =
-            hidl_request.baseConfigs.securityConfig.pmk.size();
-        if (legacy_request->key_info.body.pmk_info.pmk_len !=
-            NAN_PMK_INFO_LEN) {
-            LOG(ERROR)
-                << "convertHidlNanPublishRequestToLegacy: invalid pmk_len";
+                hidl_request.baseConfigs.securityConfig.pmk.size();
+        if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
+            LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: invalid pmk_len";
             return false;
         }
         memcpy(legacy_request->key_info.body.pmk_info.pmk,
@@ -1665,10 +1508,9 @@
     }
     if (hidl_request.baseConfigs.securityConfig.securityType ==
         NanDataPathSecurityType::PASSPHRASE) {
-        legacy_request->key_info.key_type =
-            legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
         legacy_request->key_info.body.passphrase_info.passphrase_len =
-            hidl_request.baseConfigs.securityConfig.passphrase.size();
+                hidl_request.baseConfigs.securityConfig.passphrase.size();
         if (legacy_request->key_info.body.passphrase_info.passphrase_len <
             NAN_SECURITY_MIN_PASSPHRASE_LEN) {
             LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
@@ -1686,45 +1528,36 @@
                legacy_request->key_info.body.passphrase_info.passphrase_len);
     }
     legacy_request->sdea_params.security_cfg =
-        (hidl_request.baseConfigs.securityConfig.securityType !=
-         NanDataPathSecurityType::OPEN)
-            ? legacy_hal::NAN_DP_CONFIG_SECURITY
-            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
-    legacy_request->sdea_params.ranging_state =
-        hidl_request.baseConfigs.rangingRequired
-            ? legacy_hal::NAN_RANGING_ENABLE
-            : legacy_hal::NAN_RANGING_DISABLE;
+            (hidl_request.baseConfigs.securityConfig.securityType != NanDataPathSecurityType::OPEN)
+                    ? legacy_hal::NAN_DP_CONFIG_SECURITY
+                    : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+    legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired
+                                                        ? legacy_hal::NAN_RANGING_ENABLE
+                                                        : legacy_hal::NAN_RANGING_DISABLE;
     legacy_request->ranging_cfg.ranging_interval_msec =
-        hidl_request.baseConfigs.rangingIntervalMsec;
+            hidl_request.baseConfigs.rangingIntervalMsec;
     legacy_request->ranging_cfg.config_ranging_indications =
-        hidl_request.baseConfigs.configRangingIndications;
+            hidl_request.baseConfigs.configRangingIndications;
     legacy_request->ranging_cfg.distance_ingress_mm =
-        hidl_request.baseConfigs.distanceIngressCm * 10;
-    legacy_request->ranging_cfg.distance_egress_mm =
-        hidl_request.baseConfigs.distanceEgressCm * 10;
-    legacy_request->ranging_auto_response =
-        hidl_request.baseConfigs.rangingRequired
-            ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE
-            : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
-    legacy_request->sdea_params.range_report =
-        legacy_hal::NAN_DISABLE_RANGE_REPORT;
-    legacy_request->publish_type =
-        convertHidlNanPublishTypeToLegacy(hidl_request.publishType);
+            hidl_request.baseConfigs.distanceIngressCm * 10;
+    legacy_request->ranging_cfg.distance_egress_mm = hidl_request.baseConfigs.distanceEgressCm * 10;
+    legacy_request->ranging_auto_response = hidl_request.baseConfigs.rangingRequired
+                                                    ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE
+                                                    : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
+    legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT;
+    legacy_request->publish_type = convertHidlNanPublishTypeToLegacy(hidl_request.publishType);
     legacy_request->tx_type = convertHidlNanTxTypeToLegacy(hidl_request.txType);
-    legacy_request->service_responder_policy =
-        hidl_request.autoAcceptDataPathRequests
-            ? legacy_hal::NAN_SERVICE_ACCEPT_POLICY_ALL
-            : legacy_hal::NAN_SERVICE_ACCEPT_POLICY_NONE;
+    legacy_request->service_responder_policy = hidl_request.autoAcceptDataPathRequests
+                                                       ? legacy_hal::NAN_SERVICE_ACCEPT_POLICY_ALL
+                                                       : legacy_hal::NAN_SERVICE_ACCEPT_POLICY_NONE;
 
     return true;
 }
 
-bool convertHidlNanSubscribeRequestToLegacy(
-    const NanSubscribeRequest& hidl_request,
-    legacy_hal::NanSubscribeRequest* legacy_request) {
+bool convertHidlNanSubscribeRequestToLegacy(const NanSubscribeRequest& hidl_request,
+                                            legacy_hal::NanSubscribeRequest* legacy_request) {
     if (!legacy_request) {
-        LOG(ERROR)
-            << "convertHidlNanSubscribeRequestToLegacy: legacy_request is null";
+        LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: legacy_request is null";
         return false;
     }
     *legacy_request = {};
@@ -1733,22 +1566,18 @@
     legacy_request->ttl = hidl_request.baseConfigs.ttlSec;
     legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod;
     legacy_request->subscribe_count = hidl_request.baseConfigs.discoveryCount;
-    legacy_request->service_name_len =
-        hidl_request.baseConfigs.serviceName.size();
+    legacy_request->service_name_len = hidl_request.baseConfigs.serviceName.size();
     if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
         LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
                       "service_name_len too large";
         return false;
     }
-    memcpy(legacy_request->service_name,
-           hidl_request.baseConfigs.serviceName.data(),
+    memcpy(legacy_request->service_name, hidl_request.baseConfigs.serviceName.data(),
            legacy_request->service_name_len);
-    legacy_request->subscribe_match_indicator = convertHidlNanMatchAlgToLegacy(
-        hidl_request.baseConfigs.discoveryMatchIndicator);
-    legacy_request->service_specific_info_len =
-        hidl_request.baseConfigs.serviceSpecificInfo.size();
-    if (legacy_request->service_specific_info_len >
-        NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+    legacy_request->subscribe_match_indicator =
+            convertHidlNanMatchAlgToLegacy(hidl_request.baseConfigs.discoveryMatchIndicator);
+    legacy_request->service_specific_info_len = hidl_request.baseConfigs.serviceSpecificInfo.size();
+    if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
         LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
                       "service_specific_info_len too large";
         return false;
@@ -1757,9 +1586,8 @@
            hidl_request.baseConfigs.serviceSpecificInfo.data(),
            legacy_request->service_specific_info_len);
     legacy_request->sdea_service_specific_info_len =
-        hidl_request.baseConfigs.extendedServiceSpecificInfo.size();
-    if (legacy_request->sdea_service_specific_info_len >
-        NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+            hidl_request.baseConfigs.extendedServiceSpecificInfo.size();
+    if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
         LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
                       "sdea_service_specific_info_len too large";
         return false;
@@ -1767,48 +1595,37 @@
     memcpy(legacy_request->sdea_service_specific_info,
            hidl_request.baseConfigs.extendedServiceSpecificInfo.data(),
            legacy_request->sdea_service_specific_info_len);
-    legacy_request->rx_match_filter_len =
-        hidl_request.baseConfigs.rxMatchFilter.size();
+    legacy_request->rx_match_filter_len = hidl_request.baseConfigs.rxMatchFilter.size();
     if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
         LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
                       "rx_match_filter_len too large";
         return false;
     }
-    memcpy(legacy_request->rx_match_filter,
-           hidl_request.baseConfigs.rxMatchFilter.data(),
+    memcpy(legacy_request->rx_match_filter, hidl_request.baseConfigs.rxMatchFilter.data(),
            legacy_request->rx_match_filter_len);
-    legacy_request->tx_match_filter_len =
-        hidl_request.baseConfigs.txMatchFilter.size();
+    legacy_request->tx_match_filter_len = hidl_request.baseConfigs.txMatchFilter.size();
     if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
         LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
                       "tx_match_filter_len too large";
         return false;
     }
-    memcpy(legacy_request->tx_match_filter,
-           hidl_request.baseConfigs.txMatchFilter.data(),
+    memcpy(legacy_request->tx_match_filter, hidl_request.baseConfigs.txMatchFilter.data(),
            legacy_request->tx_match_filter_len);
-    legacy_request->rssi_threshold_flag =
-        hidl_request.baseConfigs.useRssiThreshold;
+    legacy_request->rssi_threshold_flag = hidl_request.baseConfigs.useRssiThreshold;
     legacy_request->recv_indication_cfg = 0;
     legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1
-                                                                       : 0x0;
+            hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0;
     legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
+            hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
     legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
-    legacy_request->cipher_type =
-        (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType;
-    if (hidl_request.baseConfigs.securityConfig.securityType ==
-        NanDataPathSecurityType::PMK) {
-        legacy_request->key_info.key_type =
-            legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+            hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
+    legacy_request->cipher_type = (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType;
+    if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
         legacy_request->key_info.body.pmk_info.pmk_len =
-            hidl_request.baseConfigs.securityConfig.pmk.size();
-        if (legacy_request->key_info.body.pmk_info.pmk_len !=
-            NAN_PMK_INFO_LEN) {
-            LOG(ERROR)
-                << "convertHidlNanSubscribeRequestToLegacy: invalid pmk_len";
+                hidl_request.baseConfigs.securityConfig.pmk.size();
+        if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
+            LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: invalid pmk_len";
             return false;
         }
         memcpy(legacy_request->key_info.body.pmk_info.pmk,
@@ -1817,10 +1634,9 @@
     }
     if (hidl_request.baseConfigs.securityConfig.securityType ==
         NanDataPathSecurityType::PASSPHRASE) {
-        legacy_request->key_info.key_type =
-            legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
         legacy_request->key_info.body.passphrase_info.passphrase_len =
-            hidl_request.baseConfigs.securityConfig.passphrase.size();
+                hidl_request.baseConfigs.securityConfig.passphrase.size();
         if (legacy_request->key_info.body.passphrase_info.passphrase_len <
             NAN_SECURITY_MIN_PASSPHRASE_LEN) {
             LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
@@ -1838,43 +1654,34 @@
                legacy_request->key_info.body.passphrase_info.passphrase_len);
     }
     legacy_request->sdea_params.security_cfg =
-        (hidl_request.baseConfigs.securityConfig.securityType !=
-         NanDataPathSecurityType::OPEN)
-            ? legacy_hal::NAN_DP_CONFIG_SECURITY
-            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
-    legacy_request->sdea_params.ranging_state =
-        hidl_request.baseConfigs.rangingRequired
-            ? legacy_hal::NAN_RANGING_ENABLE
-            : legacy_hal::NAN_RANGING_DISABLE;
+            (hidl_request.baseConfigs.securityConfig.securityType != NanDataPathSecurityType::OPEN)
+                    ? legacy_hal::NAN_DP_CONFIG_SECURITY
+                    : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+    legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired
+                                                        ? legacy_hal::NAN_RANGING_ENABLE
+                                                        : legacy_hal::NAN_RANGING_DISABLE;
     legacy_request->ranging_cfg.ranging_interval_msec =
-        hidl_request.baseConfigs.rangingIntervalMsec;
+            hidl_request.baseConfigs.rangingIntervalMsec;
     legacy_request->ranging_cfg.config_ranging_indications =
-        hidl_request.baseConfigs.configRangingIndications;
+            hidl_request.baseConfigs.configRangingIndications;
     legacy_request->ranging_cfg.distance_ingress_mm =
-        hidl_request.baseConfigs.distanceIngressCm * 10;
-    legacy_request->ranging_cfg.distance_egress_mm =
-        hidl_request.baseConfigs.distanceEgressCm * 10;
-    legacy_request->ranging_auto_response =
-        hidl_request.baseConfigs.rangingRequired
-            ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE
-            : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
-    legacy_request->sdea_params.range_report =
-        legacy_hal::NAN_DISABLE_RANGE_REPORT;
+            hidl_request.baseConfigs.distanceIngressCm * 10;
+    legacy_request->ranging_cfg.distance_egress_mm = hidl_request.baseConfigs.distanceEgressCm * 10;
+    legacy_request->ranging_auto_response = hidl_request.baseConfigs.rangingRequired
+                                                    ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE
+                                                    : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
+    legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT;
     legacy_request->subscribe_type =
-        convertHidlNanSubscribeTypeToLegacy(hidl_request.subscribeType);
-    legacy_request->serviceResponseFilter =
-        convertHidlNanSrfTypeToLegacy(hidl_request.srfType);
-    legacy_request->serviceResponseInclude =
-        hidl_request.srfRespondIfInAddressSet
-            ? legacy_hal::NAN_SRF_INCLUDE_RESPOND
-            : legacy_hal::NAN_SRF_INCLUDE_DO_NOT_RESPOND;
+            convertHidlNanSubscribeTypeToLegacy(hidl_request.subscribeType);
+    legacy_request->serviceResponseFilter = convertHidlNanSrfTypeToLegacy(hidl_request.srfType);
+    legacy_request->serviceResponseInclude = hidl_request.srfRespondIfInAddressSet
+                                                     ? legacy_hal::NAN_SRF_INCLUDE_RESPOND
+                                                     : legacy_hal::NAN_SRF_INCLUDE_DO_NOT_RESPOND;
     legacy_request->useServiceResponseFilter =
-        hidl_request.shouldUseSrf ? legacy_hal::NAN_USE_SRF
-                                  : legacy_hal::NAN_DO_NOT_USE_SRF;
+            hidl_request.shouldUseSrf ? legacy_hal::NAN_USE_SRF : legacy_hal::NAN_DO_NOT_USE_SRF;
     legacy_request->ssiRequiredForMatchIndication =
-        hidl_request.isSsiRequiredForMatch
-            ? legacy_hal::NAN_SSI_REQUIRED_IN_MATCH_IND
-            : legacy_hal::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
+            hidl_request.isSsiRequiredForMatch ? legacy_hal::NAN_SSI_REQUIRED_IN_MATCH_IND
+                                               : legacy_hal::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
     legacy_request->num_intf_addr_present = hidl_request.intfAddr.size();
     if (legacy_request->num_intf_addr_present > NAN_MAX_SUBSCRIBE_MAX_ADDRESS) {
         LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
@@ -1882,16 +1689,15 @@
         return false;
     }
     for (int i = 0; i < legacy_request->num_intf_addr_present; i++) {
-        memcpy(legacy_request->intf_addr[i], hidl_request.intfAddr[i].data(),
-               6);
+        memcpy(legacy_request->intf_addr[i], hidl_request.intfAddr[i].data(), 6);
     }
 
     return true;
 }
 
 bool convertHidlNanTransmitFollowupRequestToLegacy(
-    const NanTransmitFollowupRequest& hidl_request,
-    legacy_hal::NanTransmitFollowupRequest* legacy_request) {
+        const NanTransmitFollowupRequest& hidl_request,
+        legacy_hal::NanTransmitFollowupRequest* legacy_request) {
     if (!legacy_request) {
         LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: "
                       "legacy_request is null";
@@ -1902,27 +1708,22 @@
     legacy_request->publish_subscribe_id = hidl_request.discoverySessionId;
     legacy_request->requestor_instance_id = hidl_request.peerId;
     memcpy(legacy_request->addr, hidl_request.addr.data(), 6);
-    legacy_request->priority = hidl_request.isHighPriority
-                                   ? legacy_hal::NAN_TX_PRIORITY_HIGH
-                                   : legacy_hal::NAN_TX_PRIORITY_NORMAL;
+    legacy_request->priority = hidl_request.isHighPriority ? legacy_hal::NAN_TX_PRIORITY_HIGH
+                                                           : legacy_hal::NAN_TX_PRIORITY_NORMAL;
     legacy_request->dw_or_faw = hidl_request.shouldUseDiscoveryWindow
-                                    ? legacy_hal::NAN_TRANSMIT_IN_DW
-                                    : legacy_hal::NAN_TRANSMIT_IN_FAW;
-    legacy_request->service_specific_info_len =
-        hidl_request.serviceSpecificInfo.size();
-    if (legacy_request->service_specific_info_len >
-        NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+                                        ? legacy_hal::NAN_TRANSMIT_IN_DW
+                                        : legacy_hal::NAN_TRANSMIT_IN_FAW;
+    legacy_request->service_specific_info_len = hidl_request.serviceSpecificInfo.size();
+    if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
         LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: "
                       "service_specific_info_len too large";
         return false;
     }
-    memcpy(legacy_request->service_specific_info,
-           hidl_request.serviceSpecificInfo.data(),
+    memcpy(legacy_request->service_specific_info, hidl_request.serviceSpecificInfo.data(),
            legacy_request->service_specific_info_len);
     legacy_request->sdea_service_specific_info_len =
-        hidl_request.extendedServiceSpecificInfo.size();
-    if (legacy_request->sdea_service_specific_info_len >
-        NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+            hidl_request.extendedServiceSpecificInfo.size();
+    if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
         LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: "
                       "sdea_service_specific_info_len too large";
         return false;
@@ -1930,18 +1731,15 @@
     memcpy(legacy_request->sdea_service_specific_info,
            hidl_request.extendedServiceSpecificInfo.data(),
            legacy_request->sdea_service_specific_info_len);
-    legacy_request->recv_indication_cfg =
-        hidl_request.disableFollowupResultIndication ? 0x1 : 0x0;
+    legacy_request->recv_indication_cfg = hidl_request.disableFollowupResultIndication ? 0x1 : 0x0;
 
     return true;
 }
 
-bool convertHidlNanConfigRequestToLegacy(
-    const V1_4::NanConfigRequest& hidl_request,
-    legacy_hal::NanConfigRequest* legacy_request) {
+bool convertHidlNanConfigRequestToLegacy(const V1_4::NanConfigRequest& hidl_request,
+                                         legacy_hal::NanConfigRequest* legacy_request) {
     if (!legacy_request) {
-        LOG(ERROR)
-            << "convertHidlNanConfigRequestToLegacy: legacy_request is null";
+        LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: legacy_request is null";
         return false;
     }
     *legacy_request = {};
@@ -1951,20 +1749,19 @@
     legacy_request->master_pref = hidl_request.masterPref;
     legacy_request->discovery_indication_cfg = 0;
     legacy_request->discovery_indication_cfg |=
-        hidl_request.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0;
+            hidl_request.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0;
     legacy_request->discovery_indication_cfg |=
-        hidl_request.disableStartedClusterIndication ? 0x2 : 0x0;
+            hidl_request.disableStartedClusterIndication ? 0x2 : 0x0;
     legacy_request->discovery_indication_cfg |=
-        hidl_request.disableJoinedClusterIndication ? 0x4 : 0x0;
+            hidl_request.disableJoinedClusterIndication ? 0x4 : 0x0;
     legacy_request->config_sid_beacon = 1;
     if (hidl_request.numberOfPublishServiceIdsInBeacon > 127) {
         LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: "
                       "numberOfPublishServiceIdsInBeacon > 127";
         return false;
     }
-    legacy_request->sid_beacon =
-        (hidl_request.includePublishServiceIdsInBeacon ? 0x1 : 0x0) |
-        (hidl_request.numberOfPublishServiceIdsInBeacon << 1);
+    legacy_request->sid_beacon = (hidl_request.includePublishServiceIdsInBeacon ? 0x1 : 0x0) |
+                                 (hidl_request.numberOfPublishServiceIdsInBeacon << 1);
     legacy_request->config_subscribe_sid_beacon = 1;
     if (hidl_request.numberOfSubscribeServiceIdsInBeacon > 127) {
         LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: "
@@ -1972,13 +1769,13 @@
         return false;
     }
     legacy_request->subscribe_sid_beacon_val =
-        (hidl_request.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) |
-        (hidl_request.numberOfSubscribeServiceIdsInBeacon << 1);
+            (hidl_request.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) |
+            (hidl_request.numberOfSubscribeServiceIdsInBeacon << 1);
     legacy_request->config_rssi_window_size = 1;
     legacy_request->rssi_window_size_val = hidl_request.rssiWindowSize;
     legacy_request->config_disc_mac_addr_randomization = 1;
     legacy_request->disc_mac_addr_rand_interval_sec =
-        hidl_request.macAddressRandomizationIntervalSec;
+            hidl_request.macAddressRandomizationIntervalSec;
     /* TODO : missing
     legacy_request->config_2dot4g_rssi_close = 1;
     legacy_request->rssi_close_2dot4g_val =
@@ -1994,20 +1791,16 @@
               (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiCloseProximity;
     */
     legacy_request->config_scan_params = 1;
-    legacy_request->scan_params_val
-        .dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
-        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
-            .dwellTimeMs;
-    legacy_request->scan_params_val
-        .scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
-        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
-            .scanPeriodSec;
+    legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
+            hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ].dwellTimeMs;
+    legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
+            hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ].scanPeriodSec;
     legacy_request->config_dw.config_2dot4g_dw_band =
-        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
-            .validDiscoveryWindowIntervalVal;
+            hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+                    .validDiscoveryWindowIntervalVal;
     legacy_request->config_dw.dw_2dot4g_interval_val =
-        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
-            .discoveryWindowIntervalVal;
+            hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+                    .discoveryWindowIntervalVal;
     /* TODO: missing
     legacy_request->config_5g_rssi_close = 1;
     legacy_request->rssi_close_5g_val =
@@ -2020,30 +1813,21 @@
     */
     legacy_request->config_5g_rssi_close_proximity = 1;
     legacy_request->rssi_close_proximity_5g_val =
-        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .rssiCloseProximity;
-    legacy_request->scan_params_val
-        .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
-        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .dwellTimeMs;
-    legacy_request->scan_params_val
-        .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
-        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .scanPeriodSec;
-    legacy_request->scan_params_val
-        .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
-        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .dwellTimeMs;
-    legacy_request->scan_params_val
-        .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
-        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .scanPeriodSec;
+            hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].rssiCloseProximity;
+    legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+            hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs;
+    legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+            hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec;
+    legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+            hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs;
+    legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+            hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec;
     legacy_request->config_dw.config_5g_dw_band =
-        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .validDiscoveryWindowIntervalVal;
+            hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+                    .validDiscoveryWindowIntervalVal;
     legacy_request->config_dw.dw_5g_interval_val =
-        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
-            .discoveryWindowIntervalVal;
+            hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+                    .discoveryWindowIntervalVal;
     /* TODO: b/145609058
      * Missing updates needed to legacy_hal::NanConfigRequest and conversion to
      * it for 6GHz band */
@@ -2051,10 +1835,9 @@
     return true;
 }
 
-bool convertHidlNanConfigRequest_1_4ToLegacy(
-    const V1_4::NanConfigRequest& hidl_request1,
-    const NanConfigRequestSupplemental& hidl_request2,
-    legacy_hal::NanConfigRequest* legacy_request) {
+bool convertHidlNanConfigRequest_1_4ToLegacy(const V1_4::NanConfigRequest& hidl_request1,
+                                             const NanConfigRequestSupplemental& hidl_request2,
+                                             legacy_hal::NanConfigRequest* legacy_request) {
     if (!legacy_request) {
         LOG(ERROR) << "convertHidlNanConfigRequest_1_4ToLegacy: legacy_request "
                       "is null";
@@ -2067,13 +1850,12 @@
     }
 
     legacy_request->config_discovery_beacon_int = 1;
-    legacy_request->discovery_beacon_interval =
-        hidl_request2.V1_2.discoveryBeaconIntervalMs;
+    legacy_request->discovery_beacon_interval = hidl_request2.V1_2.discoveryBeaconIntervalMs;
     legacy_request->config_nss = 1;
     legacy_request->nss = hidl_request2.V1_2.numberOfSpatialStreamsInDiscovery;
     legacy_request->config_dw_early_termination = 1;
     legacy_request->enable_dw_termination =
-        hidl_request2.V1_2.enableDiscoveryWindowEarlyTermination;
+            hidl_request2.V1_2.enableDiscoveryWindowEarlyTermination;
     legacy_request->config_enable_ranging = 1;
     legacy_request->enable_ranging = hidl_request2.V1_2.enableRanging;
 
@@ -2081,8 +1863,8 @@
 }
 
 bool convertHidlNanDataPathInitiatorRequestToLegacy(
-    const NanInitiateDataPathRequest& hidl_request,
-    legacy_hal::NanDataPathInitiatorRequest* legacy_request) {
+        const NanInitiateDataPathRequest& hidl_request,
+        legacy_hal::NanDataPathInitiatorRequest* legacy_request) {
     if (!legacy_request) {
         LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
                       "legacy_request is null";
@@ -2091,24 +1873,20 @@
     *legacy_request = {};
 
     legacy_request->requestor_instance_id = hidl_request.peerId;
-    memcpy(legacy_request->peer_disc_mac_addr,
-           hidl_request.peerDiscMacAddr.data(), 6);
+    memcpy(legacy_request->peer_disc_mac_addr, hidl_request.peerDiscMacAddr.data(), 6);
     legacy_request->channel_request_type =
-        convertHidlNanDataPathChannelCfgToLegacy(
-            hidl_request.channelRequestType);
+            convertHidlNanDataPathChannelCfgToLegacy(hidl_request.channelRequestType);
     legacy_request->channel = hidl_request.channel;
     if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) {
         LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
                       "ifaceName too long";
         return false;
     }
-    strncpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(),
-            IFNAMSIZ + 1);
+    strncpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1);
     legacy_request->ndp_cfg.security_cfg =
-        (hidl_request.securityConfig.securityType !=
-         NanDataPathSecurityType::OPEN)
-            ? legacy_hal::NAN_DP_CONFIG_SECURITY
-            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+            (hidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN)
+                    ? legacy_hal::NAN_DP_CONFIG_SECURITY
+                    : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
     legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
     if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
         LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
@@ -2117,30 +1895,22 @@
     }
     memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
            legacy_request->app_info.ndp_app_info_len);
-    legacy_request->cipher_type =
-        (unsigned int)hidl_request.securityConfig.cipherType;
-    if (hidl_request.securityConfig.securityType ==
-        NanDataPathSecurityType::PMK) {
-        legacy_request->key_info.key_type =
-            legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
-        legacy_request->key_info.body.pmk_info.pmk_len =
-            hidl_request.securityConfig.pmk.size();
-        if (legacy_request->key_info.body.pmk_info.pmk_len !=
-            NAN_PMK_INFO_LEN) {
+    legacy_request->cipher_type = (unsigned int)hidl_request.securityConfig.cipherType;
+    if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+        legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size();
+        if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
             LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
                           "invalid pmk_len";
             return false;
         }
-        memcpy(legacy_request->key_info.body.pmk_info.pmk,
-               hidl_request.securityConfig.pmk.data(),
+        memcpy(legacy_request->key_info.body.pmk_info.pmk, hidl_request.securityConfig.pmk.data(),
                legacy_request->key_info.body.pmk_info.pmk_len);
     }
-    if (hidl_request.securityConfig.securityType ==
-        NanDataPathSecurityType::PASSPHRASE) {
-        legacy_request->key_info.key_type =
-            legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+    if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
         legacy_request->key_info.body.passphrase_info.passphrase_len =
-            hidl_request.securityConfig.passphrase.size();
+                hidl_request.securityConfig.passphrase.size();
         if (legacy_request->key_info.body.passphrase_info.passphrase_len <
             NAN_SECURITY_MIN_PASSPHRASE_LEN) {
             LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
@@ -2163,16 +1933,15 @@
                       "service_name_len too large";
         return false;
     }
-    memcpy(legacy_request->service_name,
-           hidl_request.serviceNameOutOfBand.data(),
+    memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(),
            legacy_request->service_name_len);
 
     return true;
 }
 
 bool convertHidlNanDataPathIndicationResponseToLegacy(
-    const NanRespondToDataPathIndicationRequest& hidl_request,
-    legacy_hal::NanDataPathIndicationResponse* legacy_request) {
+        const NanRespondToDataPathIndicationRequest& hidl_request,
+        legacy_hal::NanDataPathIndicationResponse* legacy_request) {
     if (!legacy_request) {
         LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
                       "legacy_request is null";
@@ -2180,22 +1949,19 @@
     }
     *legacy_request = {};
 
-    legacy_request->rsp_code = hidl_request.acceptRequest
-                                   ? legacy_hal::NAN_DP_REQUEST_ACCEPT
-                                   : legacy_hal::NAN_DP_REQUEST_REJECT;
+    legacy_request->rsp_code = hidl_request.acceptRequest ? legacy_hal::NAN_DP_REQUEST_ACCEPT
+                                                          : legacy_hal::NAN_DP_REQUEST_REJECT;
     legacy_request->ndp_instance_id = hidl_request.ndpInstanceId;
     if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) {
         LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
                       "ifaceName too long";
         return false;
     }
-    strncpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(),
-            IFNAMSIZ + 1);
+    strncpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1);
     legacy_request->ndp_cfg.security_cfg =
-        (hidl_request.securityConfig.securityType !=
-         NanDataPathSecurityType::OPEN)
-            ? legacy_hal::NAN_DP_CONFIG_SECURITY
-            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+            (hidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN)
+                    ? legacy_hal::NAN_DP_CONFIG_SECURITY
+                    : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
     legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
     if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
         LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
@@ -2204,30 +1970,22 @@
     }
     memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
            legacy_request->app_info.ndp_app_info_len);
-    legacy_request->cipher_type =
-        (unsigned int)hidl_request.securityConfig.cipherType;
-    if (hidl_request.securityConfig.securityType ==
-        NanDataPathSecurityType::PMK) {
-        legacy_request->key_info.key_type =
-            legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
-        legacy_request->key_info.body.pmk_info.pmk_len =
-            hidl_request.securityConfig.pmk.size();
-        if (legacy_request->key_info.body.pmk_info.pmk_len !=
-            NAN_PMK_INFO_LEN) {
+    legacy_request->cipher_type = (unsigned int)hidl_request.securityConfig.cipherType;
+    if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+        legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size();
+        if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
             LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
                           "invalid pmk_len";
             return false;
         }
-        memcpy(legacy_request->key_info.body.pmk_info.pmk,
-               hidl_request.securityConfig.pmk.data(),
+        memcpy(legacy_request->key_info.body.pmk_info.pmk, hidl_request.securityConfig.pmk.data(),
                legacy_request->key_info.body.pmk_info.pmk_len);
     }
-    if (hidl_request.securityConfig.securityType ==
-        NanDataPathSecurityType::PASSPHRASE) {
-        legacy_request->key_info.key_type =
-            legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+    if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
+        legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
         legacy_request->key_info.body.passphrase_info.passphrase_len =
-            hidl_request.securityConfig.passphrase.size();
+                hidl_request.securityConfig.passphrase.size();
         if (legacy_request->key_info.body.passphrase_info.passphrase_len <
             NAN_SECURITY_MIN_PASSPHRASE_LEN) {
             LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
@@ -2250,19 +2008,16 @@
                       "service_name_len too large";
         return false;
     }
-    memcpy(legacy_request->service_name,
-           hidl_request.serviceNameOutOfBand.data(),
+    memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(),
            legacy_request->service_name_len);
 
     return true;
 }
 
-bool convertLegacyNanResponseHeaderToHidl(
-    const legacy_hal::NanResponseMsg& legacy_response,
-    WifiNanStatus* wifiNanStatus) {
+bool convertLegacyNanResponseHeaderToHidl(const legacy_hal::NanResponseMsg& legacy_response,
+                                          WifiNanStatus* wifiNanStatus) {
     if (!wifiNanStatus) {
-        LOG(ERROR)
-            << "convertLegacyNanResponseHeaderToHidl: wifiNanStatus is null";
+        LOG(ERROR) << "convertLegacyNanResponseHeaderToHidl: wifiNanStatus is null";
         return false;
     }
     *wifiNanStatus = {};
@@ -2272,9 +2027,8 @@
     return true;
 }
 
-bool convertLegacyNanCapabilitiesResponseToHidl(
-    const legacy_hal::NanCapabilities& legacy_response,
-    NanCapabilities* hidl_response) {
+bool convertLegacyNanCapabilitiesResponseToHidl(const legacy_hal::NanCapabilities& legacy_response,
+                                                V1_5::NanCapabilities* hidl_response) {
     if (!hidl_response) {
         LOG(ERROR) << "convertLegacyNanCapabilitiesResponseToHidl: "
                       "hidl_response is null";
@@ -2282,31 +2036,23 @@
     }
     *hidl_response = {};
 
-    hidl_response->V1_0.maxConcurrentClusters =
-        legacy_response.max_concurrent_nan_clusters;
+    hidl_response->V1_0.maxConcurrentClusters = legacy_response.max_concurrent_nan_clusters;
     hidl_response->V1_0.maxPublishes = legacy_response.max_publishes;
     hidl_response->V1_0.maxSubscribes = legacy_response.max_subscribes;
-    hidl_response->V1_0.maxServiceNameLen =
-        legacy_response.max_service_name_len;
-    hidl_response->V1_0.maxMatchFilterLen =
-        legacy_response.max_match_filter_len;
-    hidl_response->V1_0.maxTotalMatchFilterLen =
-        legacy_response.max_total_match_filter_len;
-    hidl_response->V1_0.maxServiceSpecificInfoLen =
-        legacy_response.max_service_specific_info_len;
+    hidl_response->V1_0.maxServiceNameLen = legacy_response.max_service_name_len;
+    hidl_response->V1_0.maxMatchFilterLen = legacy_response.max_match_filter_len;
+    hidl_response->V1_0.maxTotalMatchFilterLen = legacy_response.max_total_match_filter_len;
+    hidl_response->V1_0.maxServiceSpecificInfoLen = legacy_response.max_service_specific_info_len;
     hidl_response->V1_0.maxExtendedServiceSpecificInfoLen =
-        legacy_response.max_sdea_service_specific_info_len;
+            legacy_response.max_sdea_service_specific_info_len;
     hidl_response->V1_0.maxNdiInterfaces = legacy_response.max_ndi_interfaces;
     hidl_response->V1_0.maxNdpSessions = legacy_response.max_ndp_sessions;
     hidl_response->V1_0.maxAppInfoLen = legacy_response.max_app_info_len;
     hidl_response->V1_0.maxQueuedTransmitFollowupMsgs =
-        legacy_response.max_queued_transmit_followup_msgs;
-    hidl_response->V1_0.maxSubscribeInterfaceAddresses =
-        legacy_response.max_subscribe_address;
-    hidl_response->V1_0.supportedCipherSuites =
-        legacy_response.cipher_suites_supported;
-    hidl_response->instantCommunicationModeSupportFlag =
-        legacy_response.is_instant_mode_supported;
+            legacy_response.max_queued_transmit_followup_msgs;
+    hidl_response->V1_0.maxSubscribeInterfaceAddresses = legacy_response.max_subscribe_address;
+    hidl_response->V1_0.supportedCipherSuites = legacy_response.cipher_suites_supported;
+    hidl_response->instantCommunicationModeSupportFlag = legacy_response.is_instant_mode_supported;
 
     return true;
 }
@@ -2322,36 +2068,31 @@
     hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
     hidl_ind->peerId = legacy_ind.requestor_instance_id;
     hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr);
-    hidl_ind->serviceSpecificInfo =
-        std::vector<uint8_t>(legacy_ind.service_specific_info,
-                             legacy_ind.service_specific_info +
-                                 legacy_ind.service_specific_info_len);
-    hidl_ind->extendedServiceSpecificInfo =
-        std::vector<uint8_t>(legacy_ind.sdea_service_specific_info,
-                             legacy_ind.sdea_service_specific_info +
-                                 legacy_ind.sdea_service_specific_info_len);
-    hidl_ind->matchFilter = std::vector<uint8_t>(
-        legacy_ind.sdf_match_filter,
-        legacy_ind.sdf_match_filter + legacy_ind.sdf_match_filter_len);
+    hidl_ind->serviceSpecificInfo = std::vector<uint8_t>(
+            legacy_ind.service_specific_info,
+            legacy_ind.service_specific_info + legacy_ind.service_specific_info_len);
+    hidl_ind->extendedServiceSpecificInfo = std::vector<uint8_t>(
+            legacy_ind.sdea_service_specific_info,
+            legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len);
+    hidl_ind->matchFilter =
+            std::vector<uint8_t>(legacy_ind.sdf_match_filter,
+                                 legacy_ind.sdf_match_filter + legacy_ind.sdf_match_filter_len);
     hidl_ind->matchOccuredInBeaconFlag = legacy_ind.match_occured_flag == 1;
     hidl_ind->outOfResourceFlag = legacy_ind.out_of_resource_flag == 1;
     hidl_ind->rssiValue = legacy_ind.rssi_value;
     hidl_ind->peerCipherType = (NanCipherSuiteType)legacy_ind.peer_cipher_type;
     hidl_ind->peerRequiresSecurityEnabledInNdp =
-        legacy_ind.peer_sdea_params.security_cfg ==
-        legacy_hal::NAN_DP_CONFIG_SECURITY;
-    hidl_ind->peerRequiresRanging = legacy_ind.peer_sdea_params.ranging_state ==
-                                    legacy_hal::NAN_RANGING_ENABLE;
-    hidl_ind->rangingMeasurementInCm =
-        legacy_ind.range_info.range_measurement_mm / 10;
+            legacy_ind.peer_sdea_params.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY;
+    hidl_ind->peerRequiresRanging =
+            legacy_ind.peer_sdea_params.ranging_state == legacy_hal::NAN_RANGING_ENABLE;
+    hidl_ind->rangingMeasurementInCm = legacy_ind.range_info.range_measurement_mm / 10;
     hidl_ind->rangingIndicationType = legacy_ind.range_info.ranging_event_type;
 
     return true;
 }
 
-bool convertLegacyNanFollowupIndToHidl(
-    const legacy_hal::NanFollowupInd& legacy_ind,
-    NanFollowupReceivedInd* hidl_ind) {
+bool convertLegacyNanFollowupIndToHidl(const legacy_hal::NanFollowupInd& legacy_ind,
+                                       NanFollowupReceivedInd* hidl_ind) {
     if (!hidl_ind) {
         LOG(ERROR) << "convertLegacyNanFollowupIndToHidl: hidl_ind is null";
         return false;
@@ -2362,45 +2103,38 @@
     hidl_ind->peerId = legacy_ind.requestor_instance_id;
     hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr);
     hidl_ind->receivedInFaw = legacy_ind.dw_or_faw == 1;
-    hidl_ind->serviceSpecificInfo =
-        std::vector<uint8_t>(legacy_ind.service_specific_info,
-                             legacy_ind.service_specific_info +
-                                 legacy_ind.service_specific_info_len);
-    hidl_ind->extendedServiceSpecificInfo =
-        std::vector<uint8_t>(legacy_ind.sdea_service_specific_info,
-                             legacy_ind.sdea_service_specific_info +
-                                 legacy_ind.sdea_service_specific_info_len);
+    hidl_ind->serviceSpecificInfo = std::vector<uint8_t>(
+            legacy_ind.service_specific_info,
+            legacy_ind.service_specific_info + legacy_ind.service_specific_info_len);
+    hidl_ind->extendedServiceSpecificInfo = std::vector<uint8_t>(
+            legacy_ind.sdea_service_specific_info,
+            legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len);
 
     return true;
 }
 
-bool convertLegacyNanDataPathRequestIndToHidl(
-    const legacy_hal::NanDataPathRequestInd& legacy_ind,
-    NanDataPathRequestInd* hidl_ind) {
+bool convertLegacyNanDataPathRequestIndToHidl(const legacy_hal::NanDataPathRequestInd& legacy_ind,
+                                              NanDataPathRequestInd* hidl_ind) {
     if (!hidl_ind) {
-        LOG(ERROR)
-            << "convertLegacyNanDataPathRequestIndToHidl: hidl_ind is null";
+        LOG(ERROR) << "convertLegacyNanDataPathRequestIndToHidl: hidl_ind is null";
         return false;
     }
     *hidl_ind = {};
 
     hidl_ind->discoverySessionId = legacy_ind.service_instance_id;
-    hidl_ind->peerDiscMacAddr =
-        hidl_array<uint8_t, 6>(legacy_ind.peer_disc_mac_addr);
+    hidl_ind->peerDiscMacAddr = hidl_array<uint8_t, 6>(legacy_ind.peer_disc_mac_addr);
     hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id;
     hidl_ind->securityRequired =
-        legacy_ind.ndp_cfg.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY;
-    hidl_ind->appInfo =
-        std::vector<uint8_t>(legacy_ind.app_info.ndp_app_info,
-                             legacy_ind.app_info.ndp_app_info +
-                                 legacy_ind.app_info.ndp_app_info_len);
+            legacy_ind.ndp_cfg.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY;
+    hidl_ind->appInfo = std::vector<uint8_t>(
+            legacy_ind.app_info.ndp_app_info,
+            legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len);
 
     return true;
 }
 
-bool convertLegacyNdpChannelInfoToHidl(
-    const legacy_hal::NanChannelInfo& legacy_struct,
-    V1_2::NanDataPathChannelInfo* hidl_struct) {
+bool convertLegacyNdpChannelInfoToHidl(const legacy_hal::NanChannelInfo& legacy_struct,
+                                       V1_2::NanDataPathChannelInfo* hidl_struct) {
     if (!hidl_struct) {
         LOG(ERROR) << "convertLegacyNdpChannelInfoToHidl: hidl_struct is null";
         return false;
@@ -2409,40 +2143,33 @@
 
     hidl_struct->channelFreq = legacy_struct.channel;
     hidl_struct->channelBandwidth = convertLegacyWifiChannelWidthToHidl(
-        (legacy_hal::wifi_channel_width)legacy_struct.bandwidth);
+            (legacy_hal::wifi_channel_width)legacy_struct.bandwidth);
     hidl_struct->numSpatialStreams = legacy_struct.nss;
 
     return true;
 }
 
-bool convertLegacyNanDataPathConfirmIndToHidl(
-    const legacy_hal::NanDataPathConfirmInd& legacy_ind,
-    V1_2::NanDataPathConfirmInd* hidl_ind) {
+bool convertLegacyNanDataPathConfirmIndToHidl(const legacy_hal::NanDataPathConfirmInd& legacy_ind,
+                                              V1_2::NanDataPathConfirmInd* hidl_ind) {
     if (!hidl_ind) {
-        LOG(ERROR)
-            << "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null";
+        LOG(ERROR) << "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null";
         return false;
     }
     *hidl_ind = {};
 
     hidl_ind->V1_0.ndpInstanceId = legacy_ind.ndp_instance_id;
-    hidl_ind->V1_0.dataPathSetupSuccess =
-        legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT;
-    hidl_ind->V1_0.peerNdiMacAddr =
-        hidl_array<uint8_t, 6>(legacy_ind.peer_ndi_mac_addr);
-    hidl_ind->V1_0.appInfo =
-        std::vector<uint8_t>(legacy_ind.app_info.ndp_app_info,
-                             legacy_ind.app_info.ndp_app_info +
-                                 legacy_ind.app_info.ndp_app_info_len);
-    hidl_ind->V1_0.status.status =
-        convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code);
+    hidl_ind->V1_0.dataPathSetupSuccess = legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT;
+    hidl_ind->V1_0.peerNdiMacAddr = hidl_array<uint8_t, 6>(legacy_ind.peer_ndi_mac_addr);
+    hidl_ind->V1_0.appInfo = std::vector<uint8_t>(
+            legacy_ind.app_info.ndp_app_info,
+            legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len);
+    hidl_ind->V1_0.status.status = convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code);
     hidl_ind->V1_0.status.description = "";  // TODO: b/34059183
 
     std::vector<V1_2::NanDataPathChannelInfo> channelInfo;
     for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) {
         V1_2::NanDataPathChannelInfo hidl_struct;
-        if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i],
-                                               &hidl_struct)) {
+        if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], &hidl_struct)) {
             return false;
         }
         channelInfo.push_back(hidl_struct);
@@ -2453,8 +2180,8 @@
 }
 
 bool convertLegacyNanDataPathScheduleUpdateIndToHidl(
-    const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
-    V1_2::NanDataPathScheduleUpdateInd* hidl_ind) {
+        const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
+        V1_2::NanDataPathScheduleUpdateInd* hidl_ind) {
     if (!hidl_ind) {
         LOG(ERROR) << "convertLegacyNanDataPathScheduleUpdateIndToHidl: "
                       "hidl_ind is null";
@@ -2462,13 +2189,11 @@
     }
     *hidl_ind = {};
 
-    hidl_ind->peerDiscoveryAddress =
-        hidl_array<uint8_t, 6>(legacy_ind.peer_mac_addr);
+    hidl_ind->peerDiscoveryAddress = hidl_array<uint8_t, 6>(legacy_ind.peer_mac_addr);
     std::vector<V1_2::NanDataPathChannelInfo> channelInfo;
     for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) {
         V1_2::NanDataPathChannelInfo hidl_struct;
-        if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i],
-                                               &hidl_struct)) {
+        if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], &hidl_struct)) {
             return false;
         }
         channelInfo.push_back(hidl_struct);
@@ -2519,8 +2244,7 @@
     CHECK(false);
 }
 
-legacy_hal::wifi_channel_width convertHidlWifiChannelWidthToLegacy(
-    WifiChannelWidthInMhz type) {
+legacy_hal::wifi_channel_width convertHidlWifiChannelWidthToLegacy(WifiChannelWidthInMhz type) {
     switch (type) {
         case WifiChannelWidthInMhz::WIDTH_20:
             return legacy_hal::WIFI_CHAN_WIDTH_20;
@@ -2542,8 +2266,7 @@
     CHECK(false);
 }
 
-WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl(
-    legacy_hal::wifi_channel_width type) {
+WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl(legacy_hal::wifi_channel_width type) {
     switch (type) {
         case legacy_hal::WIFI_CHAN_WIDTH_20:
             return WifiChannelWidthInMhz::WIDTH_20;
@@ -2564,8 +2287,7 @@
     };
 }
 
-legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(
-    V1_4::RttPreamble type) {
+legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(V1_4::RttPreamble type) {
     switch (type) {
         case V1_4::RttPreamble::LEGACY:
             return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY;
@@ -2579,8 +2301,7 @@
     CHECK(false);
 }
 
-V1_4::RttPreamble convertLegacyRttPreambleToHidl(
-    legacy_hal::wifi_rtt_preamble type) {
+V1_4::RttPreamble convertLegacyRttPreambleToHidl(legacy_hal::wifi_rtt_preamble type) {
     switch (type) {
         case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY:
             return V1_4::RttPreamble::LEGACY;
@@ -2630,8 +2351,7 @@
     CHECK(false) << "Unknown legacy type: " << type;
 }
 
-legacy_hal::wifi_motion_pattern convertHidlRttMotionPatternToLegacy(
-    RttMotionPattern type) {
+legacy_hal::wifi_motion_pattern convertHidlRttMotionPatternToLegacy(RttMotionPattern type) {
     switch (type) {
         case RttMotionPattern::NOT_EXPECTED:
             return legacy_hal::WIFI_MOTION_NOT_EXPECTED;
@@ -2718,9 +2438,8 @@
     CHECK(false) << "Unknown legacy status: " << status;
 }
 
-bool convertHidlWifiChannelInfoToLegacy(
-    const WifiChannelInfo& hidl_info,
-    legacy_hal::wifi_channel_info* legacy_info) {
+bool convertHidlWifiChannelInfoToLegacy(const WifiChannelInfo& hidl_info,
+                                        legacy_hal::wifi_channel_info* legacy_info) {
     if (!legacy_info) {
         return false;
     }
@@ -2732,9 +2451,8 @@
     return true;
 }
 
-bool convertLegacyWifiChannelInfoToHidl(
-    const legacy_hal::wifi_channel_info& legacy_info,
-    WifiChannelInfo* hidl_info) {
+bool convertLegacyWifiChannelInfoToHidl(const legacy_hal::wifi_channel_info& legacy_info,
+                                        WifiChannelInfo* hidl_info) {
     if (!hidl_info) {
         return false;
     }
@@ -2753,32 +2471,28 @@
     }
     *legacy_config = {};
     CHECK(hidl_config.addr.size() == sizeof(legacy_config->addr));
-    memcpy(legacy_config->addr, hidl_config.addr.data(),
-           hidl_config.addr.size());
+    memcpy(legacy_config->addr, hidl_config.addr.data(), hidl_config.addr.size());
     legacy_config->type = convertHidlRttTypeToLegacy(hidl_config.type);
     legacy_config->peer = convertHidlRttPeerTypeToLegacy(hidl_config.peer);
-    if (!convertHidlWifiChannelInfoToLegacy(hidl_config.channel,
-                                            &legacy_config->channel)) {
+    if (!convertHidlWifiChannelInfoToLegacy(hidl_config.channel, &legacy_config->channel)) {
         return false;
     }
     legacy_config->burst_period = hidl_config.burstPeriod;
     legacy_config->num_burst = hidl_config.numBurst;
     legacy_config->num_frames_per_burst = hidl_config.numFramesPerBurst;
-    legacy_config->num_retries_per_rtt_frame =
-        hidl_config.numRetriesPerRttFrame;
+    legacy_config->num_retries_per_rtt_frame = hidl_config.numRetriesPerRttFrame;
     legacy_config->num_retries_per_ftmr = hidl_config.numRetriesPerFtmr;
     legacy_config->LCI_request = hidl_config.mustRequestLci;
     legacy_config->LCR_request = hidl_config.mustRequestLcr;
     legacy_config->burst_duration = hidl_config.burstDuration;
-    legacy_config->preamble =
-        convertHidlRttPreambleToLegacy(hidl_config.preamble);
+    legacy_config->preamble = convertHidlRttPreambleToLegacy(hidl_config.preamble);
     legacy_config->bw = convertHidlRttBwToLegacy(hidl_config.bw);
     return true;
 }
 
 bool convertHidlVectorOfRttConfigToLegacy(
-    const std::vector<V1_4::RttConfig>& hidl_configs,
-    std::vector<legacy_hal::wifi_rtt_config>* legacy_configs) {
+        const std::vector<V1_4::RttConfig>& hidl_configs,
+        std::vector<legacy_hal::wifi_rtt_config>* legacy_configs) {
     if (!legacy_configs) {
         return false;
     }
@@ -2793,9 +2507,8 @@
     return true;
 }
 
-bool convertHidlRttLciInformationToLegacy(
-    const RttLciInformation& hidl_info,
-    legacy_hal::wifi_lci_information* legacy_info) {
+bool convertHidlRttLciInformationToLegacy(const RttLciInformation& hidl_info,
+                                          legacy_hal::wifi_lci_information* legacy_info) {
     if (!legacy_info) {
         return false;
     }
@@ -2806,99 +2519,83 @@
     legacy_info->latitude_unc = hidl_info.latitudeUnc;
     legacy_info->longitude_unc = hidl_info.longitudeUnc;
     legacy_info->altitude_unc = hidl_info.altitudeUnc;
-    legacy_info->motion_pattern =
-        convertHidlRttMotionPatternToLegacy(hidl_info.motionPattern);
+    legacy_info->motion_pattern = convertHidlRttMotionPatternToLegacy(hidl_info.motionPattern);
     legacy_info->floor = hidl_info.floor;
     legacy_info->height_above_floor = hidl_info.heightAboveFloor;
     legacy_info->height_unc = hidl_info.heightUnc;
     return true;
 }
 
-bool convertHidlRttLcrInformationToLegacy(
-    const RttLcrInformation& hidl_info,
-    legacy_hal::wifi_lcr_information* legacy_info) {
+bool convertHidlRttLcrInformationToLegacy(const RttLcrInformation& hidl_info,
+                                          legacy_hal::wifi_lcr_information* legacy_info) {
     if (!legacy_info) {
         return false;
     }
     *legacy_info = {};
     CHECK(hidl_info.countryCode.size() == sizeof(legacy_info->country_code));
-    memcpy(legacy_info->country_code, hidl_info.countryCode.data(),
-           hidl_info.countryCode.size());
+    memcpy(legacy_info->country_code, hidl_info.countryCode.data(), hidl_info.countryCode.size());
     if (hidl_info.civicInfo.size() > sizeof(legacy_info->civic_info)) {
         return false;
     }
     legacy_info->length = hidl_info.civicInfo.size();
-    memcpy(legacy_info->civic_info, hidl_info.civicInfo.c_str(),
-           hidl_info.civicInfo.size());
+    memcpy(legacy_info->civic_info, hidl_info.civicInfo.c_str(), hidl_info.civicInfo.size());
     return true;
 }
 
-bool convertHidlRttResponderToLegacy(
-    const V1_4::RttResponder& hidl_responder,
-    legacy_hal::wifi_rtt_responder* legacy_responder) {
+bool convertHidlRttResponderToLegacy(const V1_4::RttResponder& hidl_responder,
+                                     legacy_hal::wifi_rtt_responder* legacy_responder) {
     if (!legacy_responder) {
         return false;
     }
     *legacy_responder = {};
-    if (!convertHidlWifiChannelInfoToLegacy(hidl_responder.channel,
-                                            &legacy_responder->channel)) {
+    if (!convertHidlWifiChannelInfoToLegacy(hidl_responder.channel, &legacy_responder->channel)) {
         return false;
     }
-    legacy_responder->preamble =
-        convertHidlRttPreambleToLegacy(hidl_responder.preamble);
+    legacy_responder->preamble = convertHidlRttPreambleToLegacy(hidl_responder.preamble);
     return true;
 }
 
-bool convertLegacyRttResponderToHidl(
-    const legacy_hal::wifi_rtt_responder& legacy_responder,
-    V1_4::RttResponder* hidl_responder) {
+bool convertLegacyRttResponderToHidl(const legacy_hal::wifi_rtt_responder& legacy_responder,
+                                     V1_4::RttResponder* hidl_responder) {
     if (!hidl_responder) {
         return false;
     }
     *hidl_responder = {};
-    if (!convertLegacyWifiChannelInfoToHidl(legacy_responder.channel,
-                                            &hidl_responder->channel)) {
+    if (!convertLegacyWifiChannelInfoToHidl(legacy_responder.channel, &hidl_responder->channel)) {
         return false;
     }
-    hidl_responder->preamble =
-        convertLegacyRttPreambleToHidl(legacy_responder.preamble);
+    hidl_responder->preamble = convertLegacyRttPreambleToHidl(legacy_responder.preamble);
     return true;
 }
 
 bool convertLegacyRttCapabilitiesToHidl(
-    const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
-    V1_4::RttCapabilities* hidl_capabilities) {
+        const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
+        V1_4::RttCapabilities* hidl_capabilities) {
     if (!hidl_capabilities) {
         return false;
     }
     *hidl_capabilities = {};
-    hidl_capabilities->rttOneSidedSupported =
-        legacy_capabilities.rtt_one_sided_supported;
+    hidl_capabilities->rttOneSidedSupported = legacy_capabilities.rtt_one_sided_supported;
     hidl_capabilities->rttFtmSupported = legacy_capabilities.rtt_ftm_supported;
     hidl_capabilities->lciSupported = legacy_capabilities.lci_support;
     hidl_capabilities->lcrSupported = legacy_capabilities.lcr_support;
-    hidl_capabilities->responderSupported =
-        legacy_capabilities.responder_supported;
+    hidl_capabilities->responderSupported = legacy_capabilities.responder_supported;
     hidl_capabilities->preambleSupport = 0;
-    for (const auto flag :
-         {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY,
-          legacy_hal::WIFI_RTT_PREAMBLE_HT, legacy_hal::WIFI_RTT_PREAMBLE_VHT,
-          legacy_hal::WIFI_RTT_PREAMBLE_HE}) {
+    for (const auto flag : {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY, legacy_hal::WIFI_RTT_PREAMBLE_HT,
+                            legacy_hal::WIFI_RTT_PREAMBLE_VHT, legacy_hal::WIFI_RTT_PREAMBLE_HE}) {
         if (legacy_capabilities.preamble_support & flag) {
             hidl_capabilities->preambleSupport |=
-                static_cast<std::underlying_type<V1_4::RttPreamble>::type>(
-                    convertLegacyRttPreambleToHidl(flag));
+                    static_cast<std::underlying_type<V1_4::RttPreamble>::type>(
+                            convertLegacyRttPreambleToHidl(flag));
         }
     }
     hidl_capabilities->bwSupport = 0;
     for (const auto flag :
-         {legacy_hal::WIFI_RTT_BW_5, legacy_hal::WIFI_RTT_BW_10,
-          legacy_hal::WIFI_RTT_BW_20, legacy_hal::WIFI_RTT_BW_40,
-          legacy_hal::WIFI_RTT_BW_80, legacy_hal::WIFI_RTT_BW_160}) {
+         {legacy_hal::WIFI_RTT_BW_5, legacy_hal::WIFI_RTT_BW_10, legacy_hal::WIFI_RTT_BW_20,
+          legacy_hal::WIFI_RTT_BW_40, legacy_hal::WIFI_RTT_BW_80, legacy_hal::WIFI_RTT_BW_160}) {
         if (legacy_capabilities.bw_support & flag) {
             hidl_capabilities->bwSupport |=
-                static_cast<std::underlying_type<RttBw>::type>(
-                    convertLegacyRttBwToHidl(flag));
+                    static_cast<std::underlying_type<RttBw>::type>(convertLegacyRttBwToHidl(flag));
         }
     }
     hidl_capabilities->mcVersion = legacy_capabilities.mc_version;
@@ -2911,26 +2608,23 @@
         return false;
     }
     *hidl_rate = {};
-    hidl_rate->preamble =
-        convertLegacyWifiRatePreambleToHidl(legacy_rate.preamble);
+    hidl_rate->preamble = convertLegacyWifiRatePreambleToHidl(legacy_rate.preamble);
     hidl_rate->nss = convertLegacyWifiRateNssToHidl(legacy_rate.nss);
     hidl_rate->bw = convertLegacyWifiChannelWidthToHidl(
-        static_cast<legacy_hal::wifi_channel_width>(legacy_rate.bw));
+            static_cast<legacy_hal::wifi_channel_width>(legacy_rate.bw));
     hidl_rate->rateMcsIdx = legacy_rate.rateMcsIdx;
     hidl_rate->bitRateInKbps = legacy_rate.bitrate;
     return true;
 }
 
-bool convertLegacyRttResultToHidl(
-    const legacy_hal::wifi_rtt_result& legacy_result,
-    V1_4::RttResult* hidl_result) {
+bool convertLegacyRttResultToHidl(const legacy_hal::wifi_rtt_result& legacy_result,
+                                  V1_4::RttResult* hidl_result) {
     if (!hidl_result) {
         return false;
     }
     *hidl_result = {};
     CHECK(sizeof(legacy_result.addr) == hidl_result->addr.size());
-    memcpy(hidl_result->addr.data(), legacy_result.addr,
-           sizeof(legacy_result.addr));
+    memcpy(hidl_result->addr.data(), legacy_result.addr, sizeof(legacy_result.addr));
     hidl_result->burstNum = legacy_result.burst_num;
     hidl_result->measurementNumber = legacy_result.measurement_number;
     hidl_result->successNumber = legacy_result.success_number;
@@ -2940,12 +2634,10 @@
     hidl_result->type = convertLegacyRttTypeToHidl(legacy_result.type);
     hidl_result->rssi = legacy_result.rssi;
     hidl_result->rssiSpread = legacy_result.rssi_spread;
-    if (!convertLegacyWifiRateInfoToHidl(legacy_result.tx_rate,
-                                         &hidl_result->txRate)) {
+    if (!convertLegacyWifiRateInfoToHidl(legacy_result.tx_rate, &hidl_result->txRate)) {
         return false;
     }
-    if (!convertLegacyWifiRateInfoToHidl(legacy_result.rx_rate,
-                                         &hidl_result->rxRate)) {
+    if (!convertLegacyWifiRateInfoToHidl(legacy_result.rx_rate, &hidl_result->rxRate)) {
         return false;
     }
     hidl_result->rtt = legacy_result.rtt;
@@ -2957,20 +2649,18 @@
     hidl_result->timeStampInUs = legacy_result.ts;
     hidl_result->burstDurationInMs = legacy_result.burst_duration;
     hidl_result->negotiatedBurstNum = legacy_result.negotiated_burst_num;
-    if (legacy_result.LCI &&
-        !convertLegacyIeToHidl(*legacy_result.LCI, &hidl_result->lci)) {
+    if (legacy_result.LCI && !convertLegacyIeToHidl(*legacy_result.LCI, &hidl_result->lci)) {
         return false;
     }
-    if (legacy_result.LCR &&
-        !convertLegacyIeToHidl(*legacy_result.LCR, &hidl_result->lcr)) {
+    if (legacy_result.LCR && !convertLegacyIeToHidl(*legacy_result.LCR, &hidl_result->lcr)) {
         return false;
     }
     return true;
 }
 
 bool convertLegacyVectorOfRttResultToHidl(
-    const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
-    std::vector<V1_4::RttResult>* hidl_results) {
+        const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
+        std::vector<V1_4::RttResult>* hidl_results) {
     if (!hidl_results) {
         return false;
     }
@@ -2985,8 +2675,7 @@
     return true;
 }
 
-legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(
-    IfaceType hidl_interface_type) {
+legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(IfaceType hidl_interface_type) {
     switch (hidl_interface_type) {
         case IfaceType::STA:
             return legacy_hal::WIFI_INTERFACE_TYPE_STA;
@@ -3001,28 +2690,28 @@
 }
 
 legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy(
-    IWifiChip::MultiStaUseCase use_case) {
+        V1_5::IWifiChip::MultiStaUseCase use_case) {
     switch (use_case) {
-        case IWifiChip::MultiStaUseCase::DUAL_STA_TRANSIENT_PREFER_PRIMARY:
+        case V1_5::IWifiChip::MultiStaUseCase::DUAL_STA_TRANSIENT_PREFER_PRIMARY:
             return legacy_hal::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY;
-        case IWifiChip::MultiStaUseCase::DUAL_STA_NON_TRANSIENT_UNBIASED:
+        case V1_5::IWifiChip::MultiStaUseCase::DUAL_STA_NON_TRANSIENT_UNBIASED:
             return legacy_hal::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED;
     }
     CHECK(false);
 }
 
 bool convertHidlCoexUnsafeChannelToLegacy(
-    const IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel,
-    legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel) {
+        const V1_5::IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel,
+        legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel) {
     if (!legacy_unsafe_channel) {
         return false;
     }
     *legacy_unsafe_channel = {};
     switch (hidl_unsafe_channel.band) {
-        case WifiBand::BAND_24GHZ:
+        case V1_5::WifiBand::BAND_24GHZ:
             legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_2_4_BAND;
             break;
-        case WifiBand::BAND_5GHZ:
+        case V1_5::WifiBand::BAND_5GHZ:
             legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_5_0_BAND;
             break;
         default:
@@ -3034,16 +2723,16 @@
 }
 
 bool convertHidlVectorOfCoexUnsafeChannelToLegacy(
-    const std::vector<IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels,
-    std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels) {
+        const std::vector<V1_5::IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels,
+        std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels) {
     if (!legacy_unsafe_channels) {
         return false;
     }
     *legacy_unsafe_channels = {};
     for (const auto& hidl_unsafe_channel : hidl_unsafe_channels) {
         legacy_hal::wifi_coex_unsafe_channel legacy_unsafe_channel;
-        if (!hidl_struct_util::convertHidlCoexUnsafeChannelToLegacy(
-                hidl_unsafe_channel, &legacy_unsafe_channel)) {
+        if (!hidl_struct_util::convertHidlCoexUnsafeChannelToLegacy(hidl_unsafe_channel,
+                                                                    &legacy_unsafe_channel)) {
             return false;
         }
         legacy_unsafe_channels->push_back(legacy_unsafe_channel);
@@ -3053,7 +2742,7 @@
 
 }  // namespace hidl_struct_util
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.6/default/hidl_struct_util.h b/wifi/1.6/default/hidl_struct_util.h
new file mode 100644
index 0000000..15a3205
--- /dev/null
+++ b/wifi/1.6/default/hidl_struct_util.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HIDL_STRUCT_UTIL_H_
+#define HIDL_STRUCT_UTIL_H_
+
+#include <vector>
+
+#include <android/hardware/wifi/1.0/IWifiChip.h>
+#include <android/hardware/wifi/1.0/types.h>
+#include <android/hardware/wifi/1.2/types.h>
+#include <android/hardware/wifi/1.3/types.h>
+#include <android/hardware/wifi/1.4/IWifiChipEventCallback.h>
+#include <android/hardware/wifi/1.4/types.h>
+#include <android/hardware/wifi/1.5/IWifiChip.h>
+#include <android/hardware/wifi/1.5/types.h>
+
+#include "wifi_legacy_hal.h"
+
+/**
+ * This file contains a bunch of functions to convert structs from the legacy
+ * HAL to HIDL and vice versa.
+ * TODO(b/32093047): Add unit tests for these conversion methods in the VTS test
+ * suite.
+ */
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_6 {
+namespace implementation {
+namespace hidl_struct_util {
+using namespace android::hardware::wifi::V1_0;
+
+// Chip conversion methods.
+bool convertLegacyFeaturesToHidlChipCapabilities(uint64_t legacy_feature_set,
+                                                 uint32_t legacy_logger_feature_set,
+                                                 uint32_t* hidl_caps);
+bool convertLegacyDebugRingBufferStatusToHidl(
+        const legacy_hal::wifi_ring_buffer_status& legacy_status,
+        WifiDebugRingBufferStatus* hidl_status);
+bool convertLegacyVectorOfDebugRingBufferStatusToHidl(
+        const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
+        std::vector<WifiDebugRingBufferStatus>* hidl_status_vec);
+bool convertLegacyWakeReasonStatsToHidl(const legacy_hal::WakeReasonStats& legacy_stats,
+                                        WifiDebugHostWakeReasonStats* hidl_stats);
+legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
+        V1_1::IWifiChip::TxPowerScenario hidl_scenario);
+legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy(
+        V1_3::IWifiChip::LatencyMode hidl_latency_mode);
+legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2(
+        V1_2::IWifiChip::TxPowerScenario hidl_scenario);
+bool convertLegacyWifiMacInfosToHidl(
+        const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
+        std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos);
+legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(IfaceType hidl_interface_type);
+legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy(
+        V1_5::IWifiChip::MultiStaUseCase use_case);
+bool convertHidlCoexUnsafeChannelToLegacy(
+        const V1_5::IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel,
+        legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel);
+bool convertHidlVectorOfCoexUnsafeChannelToLegacy(
+        const std::vector<V1_5::IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels,
+        std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels);
+
+// STA iface conversion methods.
+bool convertLegacyFeaturesToHidlStaCapabilities(uint64_t legacy_feature_set,
+                                                uint32_t legacy_logger_feature_set,
+                                                uint32_t* hidl_caps);
+bool convertLegacyApfCapabilitiesToHidl(const legacy_hal::PacketFilterCapabilities& legacy_caps,
+                                        StaApfPacketFilterCapabilities* hidl_caps);
+bool convertLegacyGscanCapabilitiesToHidl(const legacy_hal::wifi_gscan_capabilities& legacy_caps,
+                                          StaBackgroundScanCapabilities* hidl_caps);
+legacy_hal::wifi_band convertHidlWifiBandToLegacy(V1_0::WifiBand band);
+bool convertHidlGscanParamsToLegacy(const StaBackgroundScanParameters& hidl_scan_params,
+                                    legacy_hal::wifi_scan_cmd_params* legacy_scan_params);
+// |has_ie_data| indicates whether or not the wifi_scan_result includes 802.11
+// Information Elements (IEs)
+bool convertLegacyGscanResultToHidl(const legacy_hal::wifi_scan_result& legacy_scan_result,
+                                    bool has_ie_data, StaScanResult* hidl_scan_result);
+// |cached_results| is assumed to not include IEs.
+bool convertLegacyVectorOfCachedGscanResultsToHidl(
+        const std::vector<legacy_hal::wifi_cached_scan_results>& legacy_cached_scan_results,
+        std::vector<StaScanData>* hidl_scan_datas);
+bool convertLegacyLinkLayerStatsToHidl(const legacy_hal::LinkLayerStats& legacy_stats,
+                                       V1_5::StaLinkLayerStats* hidl_stats);
+bool convertLegacyRoamingCapabilitiesToHidl(
+        const legacy_hal::wifi_roaming_capabilities& legacy_caps,
+        StaRoamingCapabilities* hidl_caps);
+bool convertHidlRoamingConfigToLegacy(const StaRoamingConfig& hidl_config,
+                                      legacy_hal::wifi_roaming_config* legacy_config);
+legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy(StaRoamingState state);
+bool convertLegacyVectorOfDebugTxPacketFateToHidl(
+        const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
+        std::vector<WifiDebugTxPacketFateReport>* hidl_fates);
+bool convertLegacyVectorOfDebugRxPacketFateToHidl(
+        const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
+        std::vector<WifiDebugRxPacketFateReport>* hidl_fates);
+
+// NAN iface conversion methods.
+void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len,
+                            WifiNanStatus* wifiNanStatus);
+bool convertHidlNanEnableRequestToLegacy(const V1_4::NanEnableRequest& hidl_request,
+                                         legacy_hal::NanEnableRequest* legacy_request);
+bool convertHidlNanConfigRequestToLegacy(const V1_4::NanConfigRequest& hidl_request,
+                                         legacy_hal::NanConfigRequest* legacy_request);
+bool convertHidlNanEnableRequest_1_4ToLegacy(
+        const V1_4::NanEnableRequest& hidl_request1,
+        const V1_5::NanConfigRequestSupplemental& hidl_request2,
+        legacy_hal::NanEnableRequest* legacy_request);
+bool convertHidlNanConfigRequest_1_4ToLegacy(
+        const V1_4::NanConfigRequest& hidl_request1,
+        const V1_5::NanConfigRequestSupplemental& hidl_request2,
+        legacy_hal::NanConfigRequest* legacy_request);
+bool convertHidlNanEnableRequest_1_5ToLegacy(
+        const V1_4::NanEnableRequest& hidl_request1,
+        const V1_5::NanConfigRequestSupplemental& hidl_request2,
+        legacy_hal::NanEnableRequest* legacy_request);
+bool convertHidlNanConfigRequest_1_5ToLegacy(
+        const V1_4::NanConfigRequest& hidl_request1,
+        const V1_5::NanConfigRequestSupplemental& hidl_request2,
+        legacy_hal::NanConfigRequest* legacy_request);
+bool convertHidlNanPublishRequestToLegacy(const NanPublishRequest& hidl_request,
+                                          legacy_hal::NanPublishRequest* legacy_request);
+bool convertHidlNanSubscribeRequestToLegacy(const NanSubscribeRequest& hidl_request,
+                                            legacy_hal::NanSubscribeRequest* legacy_request);
+bool convertHidlNanTransmitFollowupRequestToLegacy(
+        const NanTransmitFollowupRequest& hidl_request,
+        legacy_hal::NanTransmitFollowupRequest* legacy_request);
+bool convertHidlNanDataPathInitiatorRequestToLegacy(
+        const NanInitiateDataPathRequest& hidl_request,
+        legacy_hal::NanDataPathInitiatorRequest* legacy_request);
+bool convertHidlNanDataPathIndicationResponseToLegacy(
+        const NanRespondToDataPathIndicationRequest& hidl_response,
+        legacy_hal::NanDataPathIndicationResponse* legacy_response);
+bool convertLegacyNanResponseHeaderToHidl(const legacy_hal::NanResponseMsg& legacy_response,
+                                          WifiNanStatus* wifiNanStatus);
+bool convertLegacyNanCapabilitiesResponseToHidl(const legacy_hal::NanCapabilities& legacy_response,
+                                                V1_5::NanCapabilities* hidl_response);
+bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind,
+                                    NanMatchInd* hidl_ind);
+bool convertLegacyNanFollowupIndToHidl(const legacy_hal::NanFollowupInd& legacy_ind,
+                                       NanFollowupReceivedInd* hidl_ind);
+bool convertLegacyNanDataPathRequestIndToHidl(const legacy_hal::NanDataPathRequestInd& legacy_ind,
+                                              NanDataPathRequestInd* hidl_ind);
+bool convertLegacyNanDataPathConfirmIndToHidl(const legacy_hal::NanDataPathConfirmInd& legacy_ind,
+                                              V1_2::NanDataPathConfirmInd* hidl_ind);
+bool convertLegacyNanDataPathScheduleUpdateIndToHidl(
+        const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
+        V1_2::NanDataPathScheduleUpdateInd* hidl_ind);
+
+// RTT controller conversion methods.
+bool convertHidlVectorOfRttConfigToLegacy(const std::vector<V1_4::RttConfig>& hidl_configs,
+                                          std::vector<legacy_hal::wifi_rtt_config>* legacy_configs);
+bool convertHidlRttLciInformationToLegacy(const RttLciInformation& hidl_info,
+                                          legacy_hal::wifi_lci_information* legacy_info);
+bool convertHidlRttLcrInformationToLegacy(const RttLcrInformation& hidl_info,
+                                          legacy_hal::wifi_lcr_information* legacy_info);
+bool convertHidlRttResponderToLegacy(const V1_4::RttResponder& hidl_responder,
+                                     legacy_hal::wifi_rtt_responder* legacy_responder);
+bool convertHidlWifiChannelInfoToLegacy(const WifiChannelInfo& hidl_info,
+                                        legacy_hal::wifi_channel_info* legacy_info);
+bool convertLegacyRttResponderToHidl(const legacy_hal::wifi_rtt_responder& legacy_responder,
+                                     V1_4::RttResponder* hidl_responder);
+bool convertLegacyRttCapabilitiesToHidl(
+        const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
+        V1_4::RttCapabilities* hidl_capabilities);
+bool convertLegacyVectorOfRttResultToHidl(
+        const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
+        std::vector<V1_4::RttResult>* hidl_results);
+uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand band);
+uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask);
+uint32_t convertHidlUsableChannelFilterToLegacy(uint32_t hidl_filter_mask);
+bool convertLegacyWifiUsableChannelsToHidl(
+        const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels,
+        std::vector<V1_5::WifiUsableChannel>* hidl_usable_channels);
+bool convertLegacyPeerInfoStatsToHidl(const legacy_hal::WifiPeerInfo& legacy_peer_info_stats,
+                                      V1_5::StaPeerInfo* hidl_peer_info_stats);
+bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate,
+                                     V1_4::WifiRateInfo* hidl_rate);
+}  // namespace hidl_struct_util
+}  // namespace implementation
+}  // namespace V1_6
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_STRUCT_UTIL_H_
diff --git a/wifi/1.5/default/hidl_sync_util.cpp b/wifi/1.6/default/hidl_sync_util.cpp
similarity index 96%
rename from wifi/1.5/default/hidl_sync_util.cpp
rename to wifi/1.6/default/hidl_sync_util.cpp
index 93eefe9..358d95e 100644
--- a/wifi/1.5/default/hidl_sync_util.cpp
+++ b/wifi/1.6/default/hidl_sync_util.cpp
@@ -23,7 +23,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace hidl_sync_util {
 
@@ -33,7 +33,7 @@
 
 }  // namespace hidl_sync_util
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/hidl_sync_util.h b/wifi/1.6/default/hidl_sync_util.h
similarity index 96%
rename from wifi/1.5/default/hidl_sync_util.h
rename to wifi/1.6/default/hidl_sync_util.h
index e706f4c..2c1c37b 100644
--- a/wifi/1.5/default/hidl_sync_util.h
+++ b/wifi/1.6/default/hidl_sync_util.h
@@ -24,13 +24,13 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace hidl_sync_util {
 std::unique_lock<std::recursive_mutex> acquireGlobalLock();
 }  // namespace hidl_sync_util
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/ringbuffer.cpp b/wifi/1.6/default/ringbuffer.cpp
similarity index 91%
rename from wifi/1.5/default/ringbuffer.cpp
rename to wifi/1.6/default/ringbuffer.cpp
index f554111..6d4ed84 100644
--- a/wifi/1.5/default/ringbuffer.cpp
+++ b/wifi/1.6/default/ringbuffer.cpp
@@ -21,7 +21,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 
 Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {}
@@ -31,8 +31,7 @@
         return;
     }
     if (input.size() > maxSize_) {
-        LOG(INFO) << "Oversized message of " << input.size()
-                  << " bytes is dropped";
+        LOG(INFO) << "Oversized message of " << input.size() << " bytes is dropped";
         return;
     }
     data_.push_back(input);
@@ -53,7 +52,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/ringbuffer.h b/wifi/1.6/default/ringbuffer.h
similarity index 95%
rename from wifi/1.5/default/ringbuffer.h
rename to wifi/1.6/default/ringbuffer.h
index 03fb37a..8571a9f 100644
--- a/wifi/1.5/default/ringbuffer.h
+++ b/wifi/1.6/default/ringbuffer.h
@@ -23,14 +23,14 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 
 /**
  * Ringbuffer object used to store debug data.
  */
 class Ringbuffer {
-   public:
+  public:
     explicit Ringbuffer(size_t maxSize);
 
     // Appends the data buffer and deletes from the front until buffer is
@@ -39,14 +39,14 @@
     const std::list<std::vector<uint8_t>>& getData() const;
     void clear();
 
-   private:
+  private:
     std::list<std::vector<uint8_t>> data_;
     size_t size_;
     size_t maxSize_;
 };
 
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/service.cpp b/wifi/1.6/default/service.cpp
similarity index 63%
rename from wifi/1.5/default/service.cpp
rename to wifi/1.6/default/service.cpp
index 3de49b2..c874d8b 100644
--- a/wifi/1.5/default/service.cpp
+++ b/wifi/1.6/default/service.cpp
@@ -30,13 +30,10 @@
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
 using android::hardware::LazyServiceRegistrar;
-using android::hardware::wifi::V1_5::implementation::feature_flags::
-    WifiFeatureFlags;
-using android::hardware::wifi::V1_5::implementation::legacy_hal::WifiLegacyHal;
-using android::hardware::wifi::V1_5::implementation::legacy_hal::
-    WifiLegacyHalFactory;
-using android::hardware::wifi::V1_5::implementation::mode_controller::
-    WifiModeController;
+using android::hardware::wifi::V1_6::implementation::feature_flags::WifiFeatureFlags;
+using android::hardware::wifi::V1_6::implementation::legacy_hal::WifiLegacyHal;
+using android::hardware::wifi::V1_6::implementation::legacy_hal::WifiLegacyHalFactory;
+using android::hardware::wifi::V1_6::implementation::mode_controller::WifiModeController;
 
 #ifdef LAZY_SERVICE
 const bool kLazyService = true;
@@ -46,30 +43,25 @@
 
 int main(int /*argc*/, char** argv) {
     signal(SIGPIPE, SIG_IGN);
-    android::base::InitLogging(
-        argv, android::base::LogdLogger(android::base::SYSTEM));
+    android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
     LOG(INFO) << "Wifi Hal is booting up...";
 
     configureRpcThreadpool(1, true /* callerWillJoin */);
 
-    const auto iface_tool =
-        std::make_shared<android::wifi_system::InterfaceTool>();
-    const auto legacy_hal_factory =
-        std::make_shared<WifiLegacyHalFactory>(iface_tool);
+    const auto iface_tool = std::make_shared<android::wifi_system::InterfaceTool>();
+    const auto legacy_hal_factory = std::make_shared<WifiLegacyHalFactory>(iface_tool);
 
     // Setup hwbinder service
-    android::sp<android::hardware::wifi::V1_5::IWifi> service =
-        new android::hardware::wifi::V1_5::implementation::Wifi(
-            iface_tool, legacy_hal_factory,
-            std::make_shared<WifiModeController>(),
-            std::make_shared<WifiFeatureFlags>());
+    android::sp<android::hardware::wifi::V1_6::IWifi> service =
+            new android::hardware::wifi::V1_6::implementation::Wifi(
+                    iface_tool, legacy_hal_factory, std::make_shared<WifiModeController>(),
+                    std::make_shared<WifiFeatureFlags>());
     if (kLazyService) {
         auto registrar = LazyServiceRegistrar::getInstance();
         CHECK_EQ(registrar.registerService(service), android::NO_ERROR)
-            << "Failed to register wifi HAL";
+                << "Failed to register wifi HAL";
     } else {
-        CHECK_EQ(service->registerAsService(), android::NO_ERROR)
-            << "Failed to register wifi HAL";
+        CHECK_EQ(service->registerAsService(), android::NO_ERROR) << "Failed to register wifi HAL";
     }
 
     joinRpcThreadpool();
diff --git a/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.6/default/tests/hidl_struct_util_unit_tests.cpp
similarity index 74%
rename from wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp
rename to wifi/1.6/default/tests/hidl_struct_util_unit_tests.cpp
index 4b4ebd6..1182a58 100644
--- a/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp
+++ b/wifi/1.6/default/tests/hidl_struct_util_unit_tests.cpp
@@ -34,7 +34,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 using ::android::hardware::wifi::V1_0::WifiChannelWidthInMhz;
@@ -44,21 +44,17 @@
 TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithOneMac) {
     std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
     legacy_hal::WifiMacInfo legacy_mac_info1 = {
-        .wlan_mac_id = kMacId1,
-        .mac_band =
-            legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_2_4_BAND};
-    legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1,
-                                                    .channel = kIfaceChannel1};
-    legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2,
-                                                    .channel = kIfaceChannel2};
+            .wlan_mac_id = kMacId1,
+            .mac_band = legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_2_4_BAND};
+    legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1, .channel = kIfaceChannel1};
+    legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2, .channel = kIfaceChannel2};
     legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
     legacy_mac_info1.iface_infos.push_back(legacy_iface_info2);
     legacy_mac_infos.push_back(legacy_mac_info1);
 
-    std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>
-        hidl_radio_mode_infos;
-    ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
-        legacy_mac_infos, &hidl_radio_mode_infos));
+    std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
+    ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(legacy_mac_infos,
+                                                                  &hidl_radio_mode_infos));
 
     ASSERT_EQ(1u, hidl_radio_mode_infos.size());
     auto hidl_radio_mode_info1 = hidl_radio_mode_infos[0];
@@ -67,65 +63,56 @@
     ASSERT_EQ(2u, hidl_radio_mode_info1.ifaceInfos.size());
     auto hidl_iface_info1 = hidl_radio_mode_info1.ifaceInfos[0];
     EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
-    EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel),
-              hidl_iface_info1.channel);
+    EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel), hidl_iface_info1.channel);
     auto hidl_iface_info2 = hidl_radio_mode_info1.ifaceInfos[1];
     EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name);
-    EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel),
-              hidl_iface_info2.channel);
+    EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel), hidl_iface_info2.channel);
 }
 
 TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) {
     std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
-    legacy_hal::WifiMacInfo legacy_mac_info1 = {
-        .wlan_mac_id = kMacId1, .mac_band = legacy_hal::WLAN_MAC_5_0_BAND};
-    legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1,
-                                                    .channel = kIfaceChannel1};
-    legacy_hal::WifiMacInfo legacy_mac_info2 = {
-        .wlan_mac_id = kMacId2, .mac_band = legacy_hal::WLAN_MAC_2_4_BAND};
-    legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2,
-                                                    .channel = kIfaceChannel2};
+    legacy_hal::WifiMacInfo legacy_mac_info1 = {.wlan_mac_id = kMacId1,
+                                                .mac_band = legacy_hal::WLAN_MAC_5_0_BAND};
+    legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1, .channel = kIfaceChannel1};
+    legacy_hal::WifiMacInfo legacy_mac_info2 = {.wlan_mac_id = kMacId2,
+                                                .mac_band = legacy_hal::WLAN_MAC_2_4_BAND};
+    legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2, .channel = kIfaceChannel2};
     legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
     legacy_mac_infos.push_back(legacy_mac_info1);
     legacy_mac_info2.iface_infos.push_back(legacy_iface_info2);
     legacy_mac_infos.push_back(legacy_mac_info2);
 
-    std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>
-        hidl_radio_mode_infos;
-    ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
-        legacy_mac_infos, &hidl_radio_mode_infos));
+    std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
+    ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(legacy_mac_infos,
+                                                                  &hidl_radio_mode_infos));
 
     ASSERT_EQ(2u, hidl_radio_mode_infos.size());
 
     // Find mac info 1.
     const auto hidl_radio_mode_info1 =
-        std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
-                     [&legacy_mac_info1](
-                         const V1_4::IWifiChipEventCallback::RadioModeInfo& x) {
-                         return x.radioId == legacy_mac_info1.wlan_mac_id;
-                     });
+            std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
+                         [&legacy_mac_info1](const V1_4::IWifiChipEventCallback::RadioModeInfo& x) {
+                             return x.radioId == legacy_mac_info1.wlan_mac_id;
+                         });
     ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info1);
     EXPECT_EQ(V1_4::WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo);
     ASSERT_EQ(1u, hidl_radio_mode_info1->ifaceInfos.size());
     auto hidl_iface_info1 = hidl_radio_mode_info1->ifaceInfos[0];
     EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
-    EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel),
-              hidl_iface_info1.channel);
+    EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel), hidl_iface_info1.channel);
 
     // Find mac info 2.
     const auto hidl_radio_mode_info2 =
-        std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
-                     [&legacy_mac_info2](
-                         const V1_4::IWifiChipEventCallback::RadioModeInfo& x) {
-                         return x.radioId == legacy_mac_info2.wlan_mac_id;
-                     });
+            std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
+                         [&legacy_mac_info2](const V1_4::IWifiChipEventCallback::RadioModeInfo& x) {
+                             return x.radioId == legacy_mac_info2.wlan_mac_id;
+                         });
     ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info2);
     EXPECT_EQ(V1_4::WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo);
     ASSERT_EQ(1u, hidl_radio_mode_info2->ifaceInfos.size());
     auto hidl_iface_info2 = hidl_radio_mode_info2->ifaceInfos[0];
     EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name);
-    EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel),
-              hidl_iface_info2.channel);
+    EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel), hidl_iface_info2.channel);
 }
 
 TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) {
@@ -143,8 +130,7 @@
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min = rand();
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max = rand();
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg = rand();
-    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples =
-        rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples = rand();
 
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu = rand();
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu = rand();
@@ -153,8 +139,7 @@
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min = rand();
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max = rand();
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg = rand();
-    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples =
-        rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples = rand();
 
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu = rand();
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu = rand();
@@ -163,8 +148,7 @@
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min = rand();
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max = rand();
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg = rand();
-    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples =
-        rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples = rand();
 
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu = rand();
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu = rand();
@@ -173,8 +157,7 @@
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min = rand();
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max = rand();
     legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg = rand();
-    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples =
-        rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples = rand();
 
     legacy_stats.iface.info.time_slicing_duty_cycle_percent = rand();
     legacy_stats.iface.num_peers = 1;
@@ -195,14 +178,14 @@
         }
 
         legacy_hal::wifi_channel_stat channel_stat1 = {
-            .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 2437, 2437, 0},
-            .on_time = 0x1111,
-            .cca_busy_time = 0x55,
+                .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 2437, 2437, 0},
+                .on_time = 0x1111,
+                .cca_busy_time = 0x55,
         };
         legacy_hal::wifi_channel_stat channel_stat2 = {
-            .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 5180, 5180, 0},
-            .on_time = 0x2222,
-            .cca_busy_time = 0x66,
+                .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 5180, 5180, 0},
+                .on_time = 0x2222,
+                .cca_busy_time = 0x66,
         };
         radio.channel_stats.push_back(channel_stat1);
         radio.channel_stats.push_back(channel_stat2);
@@ -212,30 +195,29 @@
         peer.peer_info.bssload.sta_count = rand();
         peer.peer_info.bssload.chan_util = rand();
         wifi_rate_stat rate_stat1 = {
-            .rate = {3, 1, 2, 5, 0, 0},
-            .tx_mpdu = 0,
-            .rx_mpdu = 1,
-            .mpdu_lost = 2,
-            .retries = 3,
-            .retries_short = 4,
-            .retries_long = 5,
+                .rate = {3, 1, 2, 5, 0, 0},
+                .tx_mpdu = 0,
+                .rx_mpdu = 1,
+                .mpdu_lost = 2,
+                .retries = 3,
+                .retries_short = 4,
+                .retries_long = 5,
         };
         wifi_rate_stat rate_stat2 = {
-            .rate = {2, 2, 1, 6, 0, 1},
-            .tx_mpdu = 6,
-            .rx_mpdu = 7,
-            .mpdu_lost = 8,
-            .retries = 9,
-            .retries_short = 10,
-            .retries_long = 11,
+                .rate = {2, 2, 1, 6, 0, 1},
+                .tx_mpdu = 6,
+                .rx_mpdu = 7,
+                .mpdu_lost = 8,
+                .retries = 9,
+                .retries_short = 10,
+                .retries_long = 11,
         };
         peer.rate_stats.push_back(rate_stat1);
         peer.rate_stats.push_back(rate_stat2);
     }
 
     V1_5::StaLinkLayerStats converted{};
-    hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
-                                                        &converted);
+    hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, &converted);
     EXPECT_EQ(legacy_stats.iface.beacon_rx, converted.iface.V1_0.beaconRx);
     EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.V1_0.avgRssiMgmt);
     EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu,
@@ -252,9 +234,8 @@
               converted.iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec);
     EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg,
               converted.iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec);
-    EXPECT_EQ(
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples,
-        converted.iface.wmeBeContentionTimeStats.contentionNumSamples);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples,
+              converted.iface.wmeBeContentionTimeStats.contentionNumSamples);
 
     EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu,
               converted.iface.V1_0.wmeBkPktStats.rxMpdu);
@@ -270,9 +251,8 @@
               converted.iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec);
     EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg,
               converted.iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec);
-    EXPECT_EQ(
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples,
-        converted.iface.wmeBkContentionTimeStats.contentionNumSamples);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples,
+              converted.iface.wmeBkContentionTimeStats.contentionNumSamples);
 
     EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu,
               converted.iface.V1_0.wmeViPktStats.rxMpdu);
@@ -288,9 +268,8 @@
               converted.iface.wmeViContentionTimeStats.contentionTimeMaxInUsec);
     EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg,
               converted.iface.wmeViContentionTimeStats.contentionTimeAvgInUsec);
-    EXPECT_EQ(
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples,
-        converted.iface.wmeViContentionTimeStats.contentionNumSamples);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples,
+              converted.iface.wmeViContentionTimeStats.contentionNumSamples);
 
     EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu,
               converted.iface.V1_0.wmeVoPktStats.rxMpdu);
@@ -306,29 +285,23 @@
               converted.iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec);
     EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg,
               converted.iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec);
-    EXPECT_EQ(
-        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples,
-        converted.iface.wmeVoContentionTimeStats.contentionNumSamples);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples,
+              converted.iface.wmeVoContentionTimeStats.contentionNumSamples);
 
     EXPECT_EQ(legacy_stats.iface.info.time_slicing_duty_cycle_percent,
               converted.iface.timeSliceDutyCycleInPercent);
 
     EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size());
     for (size_t i = 0; i < legacy_stats.radios.size(); i++) {
-        EXPECT_EQ(legacy_stats.radios[i].stats.radio,
-                  converted.radios[i].radioId);
-        EXPECT_EQ(legacy_stats.radios[i].stats.on_time,
-                  converted.radios[i].V1_3.V1_0.onTimeInMs);
-        EXPECT_EQ(legacy_stats.radios[i].stats.tx_time,
-                  converted.radios[i].V1_3.V1_0.txTimeInMs);
-        EXPECT_EQ(legacy_stats.radios[i].stats.rx_time,
-                  converted.radios[i].V1_3.V1_0.rxTimeInMs);
+        EXPECT_EQ(legacy_stats.radios[i].stats.radio, converted.radios[i].radioId);
+        EXPECT_EQ(legacy_stats.radios[i].stats.on_time, converted.radios[i].V1_3.V1_0.onTimeInMs);
+        EXPECT_EQ(legacy_stats.radios[i].stats.tx_time, converted.radios[i].V1_3.V1_0.txTimeInMs);
+        EXPECT_EQ(legacy_stats.radios[i].stats.rx_time, converted.radios[i].V1_3.V1_0.rxTimeInMs);
         EXPECT_EQ(legacy_stats.radios[i].stats.on_time_scan,
                   converted.radios[i].V1_3.V1_0.onTimeInMsForScan);
         EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels.size(),
                   converted.radios[i].V1_3.V1_0.txTimeInMsPerLevel.size());
-        for (size_t j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size();
-             j++) {
+        for (size_t j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size(); j++) {
             EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels[j],
                       converted.radios[i].V1_3.V1_0.txTimeInMsPerLevel[j]);
         }
@@ -344,20 +317,16 @@
                   converted.radios[i].V1_3.onTimeInMsForHs20Scan);
         EXPECT_EQ(legacy_stats.radios[i].channel_stats.size(),
                   converted.radios[i].V1_3.channelStats.size());
-        for (size_t k = 0; k < legacy_stats.radios[i].channel_stats.size();
-             k++) {
+        for (size_t k = 0; k < legacy_stats.radios[i].channel_stats.size(); k++) {
             auto& legacy_channel_st = legacy_stats.radios[i].channel_stats[k];
             EXPECT_EQ(WifiChannelWidthInMhz::WIDTH_20,
                       converted.radios[i].V1_3.channelStats[k].channel.width);
-            EXPECT_EQ(
-                WifiChannelInMhz(legacy_channel_st.channel.center_freq),
-                converted.radios[i].V1_3.channelStats[k].channel.centerFreq);
-            EXPECT_EQ(
-                WifiChannelInMhz(legacy_channel_st.channel.center_freq0),
-                converted.radios[i].V1_3.channelStats[k].channel.centerFreq0);
-            EXPECT_EQ(
-                WifiChannelInMhz(legacy_channel_st.channel.center_freq1),
-                converted.radios[i].V1_3.channelStats[k].channel.centerFreq1);
+            EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq),
+                      converted.radios[i].V1_3.channelStats[k].channel.centerFreq);
+            EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq0),
+                      converted.radios[i].V1_3.channelStats[k].channel.centerFreq0);
+            EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq1),
+                      converted.radios[i].V1_3.channelStats[k].channel.centerFreq1);
             EXPECT_EQ(legacy_channel_st.cca_busy_time,
                       converted.radios[i].V1_3.channelStats[k].ccaBusyTimeInMs);
             EXPECT_EQ(legacy_channel_st.on_time,
@@ -373,18 +342,13 @@
                   converted.iface.peers[i].chanUtil);
         for (size_t j = 0; j < legacy_stats.peers[i].rate_stats.size(); j++) {
             EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.preamble,
-                      (uint32_t)converted.iface.peers[i]
-                          .rateStats[j]
-                          .rateInfo.preamble);
-            EXPECT_EQ(
-                legacy_stats.peers[i].rate_stats[j].rate.nss,
-                (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.nss);
-            EXPECT_EQ(
-                legacy_stats.peers[i].rate_stats[j].rate.bw,
-                (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.bw);
-            EXPECT_EQ(
-                legacy_stats.peers[i].rate_stats[j].rate.rateMcsIdx,
-                converted.iface.peers[i].rateStats[j].rateInfo.rateMcsIdx);
+                      (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.preamble);
+            EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.nss,
+                      (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.nss);
+            EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.bw,
+                      (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.bw);
+            EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.rateMcsIdx,
+                      converted.iface.peers[i].rateStats[j].rateInfo.rateMcsIdx);
             EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].tx_mpdu,
                       converted.iface.peers[i].rateStats[j].txMpdu);
             EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rx_mpdu,
@@ -402,23 +366,20 @@
 
     uint32_t hidle_caps;
 
-    uint32_t legacy_feature_set =
-        WIFI_FEATURE_D2D_RTT | WIFI_FEATURE_SET_LATENCY_MODE;
-    uint32_t legacy_logger_feature_set =
-        legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
+    uint32_t legacy_feature_set = WIFI_FEATURE_D2D_RTT | WIFI_FEATURE_SET_LATENCY_MODE;
+    uint32_t legacy_logger_feature_set = legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
 
     ASSERT_TRUE(hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(
-        legacy_feature_set, legacy_logger_feature_set, &hidle_caps));
+            legacy_feature_set, legacy_logger_feature_set, &hidle_caps));
 
     EXPECT_EQ(HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA |
-                  HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS |
-                  HidlChipCaps::DEBUG_ERROR_ALERTS | HidlChipCaps::D2D_RTT |
-                  HidlChipCaps::SET_LATENCY_MODE |
-                  HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP,
+                      HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS |
+                      HidlChipCaps::DEBUG_ERROR_ALERTS | HidlChipCaps::D2D_RTT |
+                      HidlChipCaps::SET_LATENCY_MODE | HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP,
               hidle_caps);
 }
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/tests/main.cpp b/wifi/1.6/default/tests/main.cpp
similarity index 100%
rename from wifi/1.5/default/tests/main.cpp
rename to wifi/1.6/default/tests/main.cpp
diff --git a/wifi/1.5/default/tests/mock_interface_tool.cpp b/wifi/1.6/default/tests/mock_interface_tool.cpp
similarity index 100%
rename from wifi/1.5/default/tests/mock_interface_tool.cpp
rename to wifi/1.6/default/tests/mock_interface_tool.cpp
diff --git a/wifi/1.5/default/tests/mock_interface_tool.h b/wifi/1.6/default/tests/mock_interface_tool.h
similarity index 83%
rename from wifi/1.5/default/tests/mock_interface_tool.h
rename to wifi/1.6/default/tests/mock_interface_tool.h
index 0f17551..7ce3992 100644
--- a/wifi/1.5/default/tests/mock_interface_tool.h
+++ b/wifi/1.6/default/tests/mock_interface_tool.h
@@ -24,17 +24,15 @@
 namespace wifi_system {
 
 class MockInterfaceTool : public InterfaceTool {
-   public:
+  public:
     MockInterfaceTool();
 
     MOCK_METHOD1(GetUpState, bool(const char* if_name));
     MOCK_METHOD2(SetUpState, bool(const char* if_name, bool request_up));
     MOCK_METHOD1(SetWifiUpState, bool(bool request_up));
     MOCK_METHOD2(SetMacAddress,
-                 bool(const char* if_name,
-                      const std::array<uint8_t, ETH_ALEN>& address));
-    MOCK_METHOD1(GetFactoryMacAddress,
-                 std::array<uint8_t, ETH_ALEN>(const char* if_name));
+                 bool(const char* if_name, const std::array<uint8_t, ETH_ALEN>& address));
+    MOCK_METHOD1(GetFactoryMacAddress, std::array<uint8_t, ETH_ALEN>(const char* if_name));
 
 };  // class MockInterfaceTool
 
diff --git a/wifi/1.5/default/tests/mock_wifi_feature_flags.cpp b/wifi/1.6/default/tests/mock_wifi_feature_flags.cpp
similarity index 96%
rename from wifi/1.5/default/tests/mock_wifi_feature_flags.cpp
rename to wifi/1.6/default/tests/mock_wifi_feature_flags.cpp
index 2f66ba1..d10b74c 100644
--- a/wifi/1.5/default/tests/mock_wifi_feature_flags.cpp
+++ b/wifi/1.6/default/tests/mock_wifi_feature_flags.cpp
@@ -21,7 +21,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace feature_flags {
 
@@ -29,7 +29,7 @@
 
 }  // namespace feature_flags
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/tests/mock_wifi_feature_flags.h b/wifi/1.6/default/tests/mock_wifi_feature_flags.h
similarity index 88%
rename from wifi/1.5/default/tests/mock_wifi_feature_flags.h
rename to wifi/1.6/default/tests/mock_wifi_feature_flags.h
index c3877ed..fa3600a 100644
--- a/wifi/1.5/default/tests/mock_wifi_feature_flags.h
+++ b/wifi/1.6/default/tests/mock_wifi_feature_flags.h
@@ -25,22 +25,21 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace feature_flags {
 
 class MockWifiFeatureFlags : public WifiFeatureFlags {
-   public:
+  public:
     MockWifiFeatureFlags();
 
-    MOCK_METHOD1(getChipModes,
-                 std::vector<V1_0::IWifiChip::ChipMode>(bool is_primary));
+    MOCK_METHOD1(getChipModes, std::vector<V1_0::IWifiChip::ChipMode>(bool is_primary));
     MOCK_METHOD0(isApMacRandomizationDisabled, bool());
 };
 
 }  // namespace feature_flags
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/tests/mock_wifi_iface_util.cpp b/wifi/1.6/default/tests/mock_wifi_iface_util.cpp
similarity index 82%
rename from wifi/1.5/default/tests/mock_wifi_iface_util.cpp
rename to wifi/1.6/default/tests/mock_wifi_iface_util.cpp
index b101c4a..24b16cb 100644
--- a/wifi/1.5/default/tests/mock_wifi_iface_util.cpp
+++ b/wifi/1.6/default/tests/mock_wifi_iface_util.cpp
@@ -24,17 +24,16 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace iface_util {
 
-MockWifiIfaceUtil::MockWifiIfaceUtil(
-    const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+MockWifiIfaceUtil::MockWifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
+                                     const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
     : WifiIfaceUtil(iface_tool, legacy_hal) {}
 }  // namespace iface_util
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/tests/mock_wifi_iface_util.h b/wifi/1.6/default/tests/mock_wifi_iface_util.h
similarity index 71%
rename from wifi/1.5/default/tests/mock_wifi_iface_util.h
rename to wifi/1.6/default/tests/mock_wifi_iface_util.h
index 6d5f59c..2701c36 100644
--- a/wifi/1.5/default/tests/mock_wifi_iface_util.h
+++ b/wifi/1.6/default/tests/mock_wifi_iface_util.h
@@ -24,29 +24,25 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace iface_util {
 
 class MockWifiIfaceUtil : public WifiIfaceUtil {
-   public:
-    MockWifiIfaceUtil(
-        const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
-        const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
-    MOCK_METHOD1(getFactoryMacAddress,
-                 std::array<uint8_t, 6>(const std::string&));
-    MOCK_METHOD2(setMacAddress,
-                 bool(const std::string&, const std::array<uint8_t, 6>&));
+  public:
+    MockWifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
+                      const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+    MOCK_METHOD1(getFactoryMacAddress, std::array<uint8_t, 6>(const std::string&));
+    MOCK_METHOD2(setMacAddress, bool(const std::string&, const std::array<uint8_t, 6>&));
     MOCK_METHOD0(getOrCreateRandomMacAddress, std::array<uint8_t, 6>());
-    MOCK_METHOD2(registerIfaceEventHandlers,
-                 void(const std::string&, IfaceEventHandlers));
+    MOCK_METHOD2(registerIfaceEventHandlers, void(const std::string&, IfaceEventHandlers));
     MOCK_METHOD1(unregisterIfaceEventHandlers, void(const std::string&));
     MOCK_METHOD2(setUpState, bool(const std::string&, bool));
     MOCK_METHOD1(ifNameToIndex, unsigned(const std::string&));
 };
 }  // namespace iface_util
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.6/default/tests/mock_wifi_legacy_hal.cpp
similarity index 83%
rename from wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp
rename to wifi/1.6/default/tests/mock_wifi_legacy_hal.cpp
index d13c556..2c55861 100644
--- a/wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp
+++ b/wifi/1.6/default/tests/mock_wifi_legacy_hal.cpp
@@ -24,17 +24,16 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace legacy_hal {
 
-MockWifiLegacyHal::MockWifiLegacyHal(
-    const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
-    const wifi_hal_fn& fn, bool is_primary)
+MockWifiLegacyHal::MockWifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
+                                     const wifi_hal_fn& fn, bool is_primary)
     : WifiLegacyHal(iface_tool, fn, is_primary) {}
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.6/default/tests/mock_wifi_legacy_hal.h b/wifi/1.6/default/tests/mock_wifi_legacy_hal.h
new file mode 100644
index 0000000..b1f5327
--- /dev/null
+++ b/wifi/1.6/default/tests/mock_wifi_legacy_hal.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MOCK_WIFI_LEGACY_HAL_H_
+#define MOCK_WIFI_LEGACY_HAL_H_
+
+#include <gmock/gmock.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_6 {
+namespace implementation {
+namespace legacy_hal {
+
+class MockWifiLegacyHal : public WifiLegacyHal {
+  public:
+    MockWifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
+                      const wifi_hal_fn& fn, bool is_primary);
+    MOCK_METHOD0(initialize, wifi_error());
+    MOCK_METHOD0(start, wifi_error());
+    MOCK_METHOD2(stop,
+                 wifi_error(std::unique_lock<std::recursive_mutex>*, const std::function<void()>&));
+    MOCK_METHOD2(setDfsFlag, wifi_error(const std::string&, bool));
+    MOCK_METHOD2(registerRadioModeChangeCallbackHandler,
+                 wifi_error(const std::string&, const on_radio_mode_change_callback&));
+    MOCK_METHOD1(getFirmwareVersion,
+                 std::pair<wifi_error, std::string>(const std::string& iface_name));
+    MOCK_METHOD1(getDriverVersion,
+                 std::pair<wifi_error, std::string>(const std::string& iface_name));
+
+    MOCK_METHOD2(selectTxPowerScenario,
+                 wifi_error(const std::string& iface_name, wifi_power_scenario scenario));
+    MOCK_METHOD1(resetTxPowerScenario, wifi_error(const std::string& iface_name));
+    MOCK_METHOD2(nanRegisterCallbackHandlers,
+                 wifi_error(const std::string&, const NanCallbackHandlers&));
+    MOCK_METHOD2(nanDisableRequest, wifi_error(const std::string&, transaction_id));
+    MOCK_METHOD3(nanDataInterfaceDelete,
+                 wifi_error(const std::string&, transaction_id, const std::string&));
+    MOCK_METHOD2(createVirtualInterface,
+                 wifi_error(const std::string& ifname, wifi_interface_type iftype));
+    MOCK_METHOD1(deleteVirtualInterface, wifi_error(const std::string& ifname));
+    MOCK_METHOD0(waitForDriverReady, wifi_error());
+};
+}  // namespace legacy_hal
+}  // namespace implementation
+}  // namespace V1_6
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // MOCK_WIFI_LEGACY_HAL_H_
diff --git a/wifi/1.5/default/tests/mock_wifi_mode_controller.cpp b/wifi/1.6/default/tests/mock_wifi_mode_controller.cpp
similarity index 96%
rename from wifi/1.5/default/tests/mock_wifi_mode_controller.cpp
rename to wifi/1.6/default/tests/mock_wifi_mode_controller.cpp
index e7ab22a..446f829 100644
--- a/wifi/1.5/default/tests/mock_wifi_mode_controller.cpp
+++ b/wifi/1.6/default/tests/mock_wifi_mode_controller.cpp
@@ -24,14 +24,14 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace mode_controller {
 
 MockWifiModeController::MockWifiModeController() : WifiModeController() {}
 }  // namespace mode_controller
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/tests/mock_wifi_mode_controller.h b/wifi/1.6/default/tests/mock_wifi_mode_controller.h
similarity index 96%
rename from wifi/1.5/default/tests/mock_wifi_mode_controller.h
rename to wifi/1.6/default/tests/mock_wifi_mode_controller.h
index b9151f1..addcc81 100644
--- a/wifi/1.5/default/tests/mock_wifi_mode_controller.h
+++ b/wifi/1.6/default/tests/mock_wifi_mode_controller.h
@@ -24,12 +24,12 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace mode_controller {
 
 class MockWifiModeController : public WifiModeController {
-   public:
+  public:
     MockWifiModeController();
     MOCK_METHOD0(initialize, bool());
     MOCK_METHOD1(changeFirmwareMode, bool(IfaceType));
@@ -38,7 +38,7 @@
 };
 }  // namespace mode_controller
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/tests/ringbuffer_unit_tests.cpp b/wifi/1.6/default/tests/ringbuffer_unit_tests.cpp
similarity index 98%
rename from wifi/1.5/default/tests/ringbuffer_unit_tests.cpp
rename to wifi/1.6/default/tests/ringbuffer_unit_tests.cpp
index 6fd34ee..eb86194 100644
--- a/wifi/1.5/default/tests/ringbuffer_unit_tests.cpp
+++ b/wifi/1.6/default/tests/ringbuffer_unit_tests.cpp
@@ -24,11 +24,11 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 
 class RingbufferTest : public Test {
-   public:
+  public:
     const uint32_t maxBufferSize_ = 10;
     Ringbuffer buffer_{maxBufferSize_};
 };
@@ -91,7 +91,7 @@
     EXPECT_EQ(input, buffer_.getData().front());
 }
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/tests/runtests.sh b/wifi/1.6/default/tests/runtests.sh
similarity index 100%
rename from wifi/1.5/default/tests/runtests.sh
rename to wifi/1.6/default/tests/runtests.sh
diff --git a/wifi/1.5/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.6/default/tests/wifi_chip_unit_tests.cpp
similarity index 74%
rename from wifi/1.5/default/tests/wifi_chip_unit_tests.cpp
rename to wifi/1.6/default/tests/wifi_chip_unit_tests.cpp
index 0ad6f3e..5390411 100644
--- a/wifi/1.5/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.6/default/tests/wifi_chip_unit_tests.cpp
@@ -41,11 +41,11 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 
 class WifiChipTest : public Test {
-   protected:
+  protected:
     void setupV1IfaceCombination() {
         // clang-format off
         const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinationsSta = {
@@ -59,8 +59,7 @@
             {feature_flags::chip_mode_ids::kV1Ap, combinationsAp}
         };
         // clang-format on
-        EXPECT_CALL(*feature_flags_, getChipModes(true))
-            .WillRepeatedly(testing::Return(modes));
+        EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
     }
 
     void setupV1_AwareIfaceCombination() {
@@ -76,8 +75,7 @@
             {feature_flags::chip_mode_ids::kV1Ap, combinationsAp}
         };
         // clang-format on
-        EXPECT_CALL(*feature_flags_, getChipModes(true))
-            .WillRepeatedly(testing::Return(modes));
+        EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
     }
 
     void setupV1_AwareDisabledApIfaceCombination() {
@@ -89,8 +87,7 @@
             {feature_flags::chip_mode_ids::kV1Sta, combinationsSta}
         };
         // clang-format on
-        EXPECT_CALL(*feature_flags_, getChipModes(true))
-            .WillRepeatedly(testing::Return(modes));
+        EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
     }
 
     void setupV2_AwareIfaceCombination() {
@@ -103,8 +100,7 @@
             {feature_flags::chip_mode_ids::kV3, combinations}
         };
         // clang-format on
-        EXPECT_CALL(*feature_flags_, getChipModes(true))
-            .WillRepeatedly(testing::Return(modes));
+        EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
     }
 
     void setupV2_AwareDisabledApIfaceCombination() {
@@ -116,8 +112,7 @@
             {feature_flags::chip_mode_ids::kV3, combinations}
         };
         // clang-format on
-        EXPECT_CALL(*feature_flags_, getChipModes(true))
-            .WillRepeatedly(testing::Return(modes));
+        EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
     }
 
     void setup_MultiIfaceCombination() {
@@ -129,39 +124,35 @@
             {feature_flags::chip_mode_ids::kV3, combinations}
         };
         // clang-format on
-        EXPECT_CALL(*feature_flags_, getChipModes(true))
-            .WillRepeatedly(testing::Return(modes));
+        EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
     }
 
     void assertNumberOfModes(uint32_t num_modes) {
-        chip_->getAvailableModes(
-            [num_modes](const WifiStatus& status,
-                        const std::vector<WifiChip::ChipMode>& modes) {
-                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-                // V2_Aware has 1 mode of operation.
-                ASSERT_EQ(num_modes, modes.size());
-            });
+        chip_->getAvailableModes([num_modes](const WifiStatus& status,
+                                             const std::vector<WifiChip::ChipMode>& modes) {
+            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+            // V2_Aware has 1 mode of operation.
+            ASSERT_EQ(num_modes, modes.size());
+        });
     }
 
     void findModeAndConfigureForIfaceType(const IfaceType& type) {
         // This should be aligned with kInvalidModeId in wifi_chip.cpp.
         ChipModeId mode_id = UINT32_MAX;
-        chip_->getAvailableModes(
-            [&mode_id, &type](const WifiStatus& status,
-                              const std::vector<WifiChip::ChipMode>& modes) {
-                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-                for (const auto& mode : modes) {
-                    for (const auto& combination : mode.availableCombinations) {
-                        for (const auto& limit : combination.limits) {
-                            if (limit.types.end() !=
-                                std::find(limit.types.begin(),
-                                          limit.types.end(), type)) {
-                                mode_id = mode.id;
-                            }
+        chip_->getAvailableModes([&mode_id, &type](const WifiStatus& status,
+                                                   const std::vector<WifiChip::ChipMode>& modes) {
+            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+            for (const auto& mode : modes) {
+                for (const auto& combination : mode.availableCombinations) {
+                    for (const auto& limit : combination.limits) {
+                        if (limit.types.end() !=
+                            std::find(limit.types.begin(), limit.types.end(), type)) {
+                            mode_id = mode.id;
                         }
                     }
                 }
-            });
+            }
+        });
         ASSERT_NE(UINT32_MAX, mode_id);
 
         chip_->configureChip(mode_id, [](const WifiStatus& status) {
@@ -174,58 +165,53 @@
         std::string iface_name;
         if (type == IfaceType::AP) {
             chip_->createApIface(
-                [&iface_name](const WifiStatus& status,
-                              const sp<V1_0::IWifiApIface>& iface) {
-                    if (WifiStatusCode::SUCCESS == status.code) {
-                        ASSERT_NE(iface.get(), nullptr);
-                        iface->getName([&iface_name](const WifiStatus& status,
-                                                     const hidl_string& name) {
-                            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-                            iface_name = name.c_str();
-                        });
-                    }
-                });
+                    [&iface_name](const WifiStatus& status, const sp<V1_0::IWifiApIface>& iface) {
+                        if (WifiStatusCode::SUCCESS == status.code) {
+                            ASSERT_NE(iface.get(), nullptr);
+                            iface->getName([&iface_name](const WifiStatus& status,
+                                                         const hidl_string& name) {
+                                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                                iface_name = name.c_str();
+                            });
+                        }
+                    });
         } else if (type == IfaceType::NAN) {
             chip_->createNanIface(
-                [&iface_name](
-                    const WifiStatus& status,
-                    const sp<android::hardware::wifi::V1_0::IWifiNanIface>&
-                        iface) {
-                    if (WifiStatusCode::SUCCESS == status.code) {
-                        ASSERT_NE(iface.get(), nullptr);
-                        iface->getName([&iface_name](const WifiStatus& status,
-                                                     const hidl_string& name) {
-                            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-                            iface_name = name.c_str();
-                        });
-                    }
-                });
+                    [&iface_name](const WifiStatus& status,
+                                  const sp<android::hardware::wifi::V1_0::IWifiNanIface>& iface) {
+                        if (WifiStatusCode::SUCCESS == status.code) {
+                            ASSERT_NE(iface.get(), nullptr);
+                            iface->getName([&iface_name](const WifiStatus& status,
+                                                         const hidl_string& name) {
+                                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                                iface_name = name.c_str();
+                            });
+                        }
+                    });
         } else if (type == IfaceType::P2P) {
             chip_->createP2pIface(
-                [&iface_name](const WifiStatus& status,
-                              const sp<IWifiP2pIface>& iface) {
-                    if (WifiStatusCode::SUCCESS == status.code) {
-                        ASSERT_NE(iface.get(), nullptr);
-                        iface->getName([&iface_name](const WifiStatus& status,
-                                                     const hidl_string& name) {
-                            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-                            iface_name = name.c_str();
-                        });
-                    }
-                });
+                    [&iface_name](const WifiStatus& status, const sp<IWifiP2pIface>& iface) {
+                        if (WifiStatusCode::SUCCESS == status.code) {
+                            ASSERT_NE(iface.get(), nullptr);
+                            iface->getName([&iface_name](const WifiStatus& status,
+                                                         const hidl_string& name) {
+                                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                                iface_name = name.c_str();
+                            });
+                        }
+                    });
         } else if (type == IfaceType::STA) {
             chip_->createStaIface(
-                [&iface_name](const WifiStatus& status,
-                              const sp<V1_0::IWifiStaIface>& iface) {
-                    if (WifiStatusCode::SUCCESS == status.code) {
-                        ASSERT_NE(iface.get(), nullptr);
-                        iface->getName([&iface_name](const WifiStatus& status,
-                                                     const hidl_string& name) {
-                            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-                            iface_name = name.c_str();
-                        });
-                    }
-                });
+                    [&iface_name](const WifiStatus& status, const sp<V1_0::IWifiStaIface>& iface) {
+                        if (WifiStatusCode::SUCCESS == status.code) {
+                            ASSERT_NE(iface.get(), nullptr);
+                            iface->getName([&iface_name](const WifiStatus& status,
+                                                         const hidl_string& name) {
+                                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                                iface_name = name.c_str();
+                            });
+                        }
+                    });
         }
         return iface_name;
     }
@@ -253,13 +239,12 @@
     bool createRttController() {
         bool success = false;
         chip_->createRttController_1_4(
-            NULL, [&success](const WifiStatus& status,
-                             const sp<IWifiRttController>& rtt) {
-                if (WifiStatusCode::SUCCESS == status.code) {
-                    ASSERT_NE(rtt.get(), nullptr);
-                    success = true;
-                }
-            });
+                NULL, [&success](const WifiStatus& status, const sp<IWifiRttController>& rtt) {
+                    if (WifiStatusCode::SUCCESS == status.code) {
+                        ASSERT_NE(rtt.get(), nullptr);
+                        success = true;
+                    }
+                });
         return success;
     }
 
@@ -269,27 +254,25 @@
     ChipId chip_id_ = kFakeChipId;
     legacy_hal::wifi_hal_fn fake_func_table_;
     std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
-        new NiceMock<wifi_system::MockInterfaceTool>};
+            new NiceMock<wifi_system::MockInterfaceTool>};
     std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
-        new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_,
-                                                    fake_func_table_, true)};
-    std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>>
-        mode_controller_{new NiceMock<mode_controller::MockWifiModeController>};
+            new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_, fake_func_table_, true)};
+    std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>> mode_controller_{
+            new NiceMock<mode_controller::MockWifiModeController>};
     std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
-        new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_, legacy_hal_)};
-    std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
-        feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
+            new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_, legacy_hal_)};
+    std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>> feature_flags_{
+            new NiceMock<feature_flags::MockWifiFeatureFlags>};
 
-   public:
+  public:
     void SetUp() override {
-        chip_ =
-            new WifiChip(chip_id_, true, legacy_hal_, mode_controller_,
-                         iface_util_, feature_flags_, subsystemRestartHandler);
+        chip_ = new WifiChip(chip_id_, true, legacy_hal_, mode_controller_, iface_util_,
+                             feature_flags_, subsystemRestartHandler);
 
         EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_))
-            .WillRepeatedly(testing::Return(true));
+                .WillRepeatedly(testing::Return(true));
         EXPECT_CALL(*legacy_hal_, start())
-            .WillRepeatedly(testing::Return(legacy_hal::WIFI_SUCCESS));
+                .WillRepeatedly(testing::Return(legacy_hal::WIFI_SUCCESS));
     }
 
     void TearDown() override {
@@ -305,7 +288,7 @@
 // Mode 1 - STA + P2P
 // Mode 2 - AP
 class WifiChipV1IfaceCombinationTest : public WifiChipTest {
-   public:
+  public:
     void SetUp() override {
         setupV1IfaceCombination();
         WifiChipTest::SetUp();
@@ -364,7 +347,7 @@
 // Mode 1 - STA + P2P/NAN
 // Mode 2 - AP
 class WifiChipV1_AwareIfaceCombinationTest : public WifiChipTest {
-   public:
+  public:
     void SetUp() override {
         setupV1_AwareIfaceCombination();
         WifiChipTest::SetUp();
@@ -393,30 +376,26 @@
     ASSERT_TRUE(createIface(IfaceType::AP).empty());
 }
 
-TEST_F(WifiChipV1_AwareIfaceCombinationTest,
-       StaMode_CreateStaP2p_ShouldSucceed) {
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaP2p_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     ASSERT_FALSE(createIface(IfaceType::P2P).empty());
 }
 
-TEST_F(WifiChipV1_AwareIfaceCombinationTest,
-       StaMode_CreateStaNan_ShouldSucceed) {
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaNan_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     ASSERT_FALSE(createIface(IfaceType::NAN).empty());
 }
 
-TEST_F(WifiChipV1_AwareIfaceCombinationTest,
-       StaMode_CreateStaP2PNan_ShouldFail) {
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaP2PNan_ShouldFail) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     ASSERT_FALSE(createIface(IfaceType::P2P).empty());
     ASSERT_TRUE(createIface(IfaceType::NAN).empty());
 }
 
-TEST_F(WifiChipV1_AwareIfaceCombinationTest,
-       StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     const auto p2p_iface_name = createIface(IfaceType::P2P);
@@ -428,8 +407,7 @@
     ASSERT_FALSE(createIface(IfaceType::NAN).empty());
 }
 
-TEST_F(WifiChipV1_AwareIfaceCombinationTest,
-       StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     const auto nan_iface_name = createIface(IfaceType::NAN);
@@ -488,31 +466,27 @@
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
     EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
-        .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+            .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
     chip_->selectTxPowerScenario_1_2(
-        V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
-        [](const WifiStatus& status) {
-            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-        });
+            V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+            [](const WifiStatus& status) { ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); });
 }
 
 TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) {
     findModeAndConfigureForIfaceType(IfaceType::AP);
     ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
     EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
-        .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+            .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
     chip_->selectTxPowerScenario_1_2(
-        V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
-        [](const WifiStatus& status) {
-            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-        });
+            V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+            [](const WifiStatus& status) { ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); });
 }
 
 ////////// V2 + Aware Iface Combinations ////////////
 // Mode 1 - STA + STA/AP
 //        - STA + P2P/NAN
 class WifiChipV2_AwareIfaceCombinationTest : public WifiChipTest {
-   public:
+  public:
     void SetUp() override {
         setupV2_AwareIfaceCombination();
         WifiChipTest::SetUp();
@@ -559,8 +533,7 @@
     ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
 }
 
-TEST_F(WifiChipV2_AwareIfaceCombinationTest,
-       CreateSta_AfterStaApRemove_ShouldSucceed) {
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateSta_AfterStaApRemove_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     const auto sta_iface_name = createIface(IfaceType::STA);
     ASSERT_FALSE(sta_iface_name.empty());
@@ -594,8 +567,7 @@
     ASSERT_TRUE(createIface(IfaceType::NAN).empty());
 }
 
-TEST_F(WifiChipV2_AwareIfaceCombinationTest,
-       CreateStaNan_AfterP2pRemove_ShouldSucceed) {
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaNan_AfterP2pRemove_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     const auto p2p_iface_name = createIface(IfaceType::P2P);
@@ -607,8 +579,7 @@
     ASSERT_FALSE(createIface(IfaceType::NAN).empty());
 }
 
-TEST_F(WifiChipV2_AwareIfaceCombinationTest,
-       CreateStaP2p_AfterNanRemove_ShouldSucceed) {
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2p_AfterNanRemove_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     const auto nan_iface_name = createIface(IfaceType::NAN);
@@ -632,8 +603,7 @@
     ASSERT_TRUE(createIface(IfaceType::P2P).empty());
 }
 
-TEST_F(WifiChipV2_AwareIfaceCombinationTest,
-       StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     const auto p2p_iface_name = createIface(IfaceType::P2P);
@@ -645,8 +615,7 @@
     ASSERT_FALSE(createIface(IfaceType::NAN).empty());
 }
 
-TEST_F(WifiChipV2_AwareIfaceCombinationTest,
-       StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     const auto nan_iface_name = createIface(IfaceType::NAN);
@@ -658,8 +627,7 @@
     ASSERT_FALSE(createIface(IfaceType::P2P).empty());
 }
 
-TEST_F(WifiChipV2_AwareIfaceCombinationTest,
-       CreateStaAp_EnsureDifferentIfaceNames) {
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaAp_EnsureDifferentIfaceNames) {
     findModeAndConfigureForIfaceType(IfaceType::AP);
     const auto sta_iface_name = createIface(IfaceType::STA);
     const auto ap_iface_name = createIface(IfaceType::AP);
@@ -690,28 +658,23 @@
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
     EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
-        .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+            .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
     chip_->selectTxPowerScenario_1_2(
-        V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
-        [](const WifiStatus& status) {
-            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-        });
+            V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+            [](const WifiStatus& status) { ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); });
 }
 
 TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) {
     findModeAndConfigureForIfaceType(IfaceType::AP);
     ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
     EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan1", testing::_))
-        .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+            .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
     chip_->selectTxPowerScenario_1_2(
-        V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
-        [](const WifiStatus& status) {
-            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-        });
+            V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+            [](const WifiStatus& status) { ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); });
 }
 
-TEST_F(WifiChipV2_AwareIfaceCombinationTest,
-       InvalidateAndRemoveNanOnStaRemove) {
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, InvalidateAndRemoveNanOnStaRemove) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
 
@@ -719,64 +682,55 @@
     ASSERT_EQ(createIface(IfaceType::NAN), "wlan0");
 
     // We should have 1 nan iface.
-    chip_->getNanIfaceNames(
-        [](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
-            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-            ASSERT_EQ(iface_names.size(), 1u);
-            ASSERT_EQ(iface_names[0], "wlan0");
-        });
+    chip_->getNanIfaceNames([](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
+        ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+        ASSERT_EQ(iface_names.size(), 1u);
+        ASSERT_EQ(iface_names[0], "wlan0");
+    });
     // Retrieve the exact iface object.
     sp<android::hardware::wifi::V1_0::IWifiNanIface> nan_iface;
-    chip_->getNanIface(
-        "wlan0",
-        [&nan_iface](
-            const WifiStatus& status,
-            const sp<android::hardware::wifi::V1_0::IWifiNanIface>& iface) {
-            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-            ASSERT_NE(iface.get(), nullptr);
-            nan_iface = iface;
-        });
+    chip_->getNanIface("wlan0",
+                       [&nan_iface](const WifiStatus& status,
+                                    const sp<android::hardware::wifi::V1_0::IWifiNanIface>& iface) {
+                           ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                           ASSERT_NE(iface.get(), nullptr);
+                           nan_iface = iface;
+                       });
 
     // Remove the STA iface.
     removeIface(IfaceType::STA, "wlan0");
     // We should have 0 nan iface now.
-    chip_->getNanIfaceNames(
-        [](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
-            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-            ASSERT_EQ(iface_names.size(), 0u);
-        });
+    chip_->getNanIfaceNames([](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
+        ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+        ASSERT_EQ(iface_names.size(), 0u);
+    });
     // Any operation on the nan iface object should return error now.
-    nan_iface->getName(
-        [](const WifiStatus& status, const std::string& /* iface_name */) {
-            ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID, status.code);
-        });
+    nan_iface->getName([](const WifiStatus& status, const std::string& /* iface_name */) {
+        ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID, status.code);
+    });
 }
 
-TEST_F(WifiChipV2_AwareIfaceCombinationTest,
-       InvalidateAndRemoveRttControllerOnStaRemove) {
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, InvalidateAndRemoveRttControllerOnStaRemove) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
 
     // Create RTT controller
     sp<IWifiRttController> rtt_controller;
     chip_->createRttController_1_4(
-        NULL, [&rtt_controller](const WifiStatus& status,
-                                const sp<IWifiRttController>& rtt) {
-            if (WifiStatusCode::SUCCESS == status.code) {
-                ASSERT_NE(rtt.get(), nullptr);
-                rtt_controller = rtt;
-            }
-        });
+            NULL, [&rtt_controller](const WifiStatus& status, const sp<IWifiRttController>& rtt) {
+                if (WifiStatusCode::SUCCESS == status.code) {
+                    ASSERT_NE(rtt.get(), nullptr);
+                    rtt_controller = rtt;
+                }
+            });
 
     // Remove the STA iface.
     removeIface(IfaceType::STA, "wlan0");
 
     // Any operation on the rtt controller object should return error now.
-    rtt_controller->getBoundIface(
-        [](const WifiStatus& status, const sp<IWifiIface>& /* iface */) {
-            ASSERT_EQ(WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                      status.code);
-        });
+    rtt_controller->getBoundIface([](const WifiStatus& status, const sp<IWifiIface>& /* iface */) {
+        ASSERT_EQ(WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, status.code);
+    });
 }
 
 TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNanWithSharedNanIface) {
@@ -792,28 +746,24 @@
     property_set("wifi.aware.interface", "aware0");
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
-    EXPECT_CALL(*iface_util_, ifNameToIndex("aware0"))
-        .WillOnce(testing::Return(4));
-    EXPECT_CALL(*iface_util_, setUpState("aware0", true))
-        .WillOnce(testing::Return(true));
+    EXPECT_CALL(*iface_util_, ifNameToIndex("aware0")).WillOnce(testing::Return(4));
+    EXPECT_CALL(*iface_util_, setUpState("aware0", true)).WillOnce(testing::Return(true));
     ASSERT_EQ(createIface(IfaceType::NAN), "aware0");
 
-    EXPECT_CALL(*iface_util_, setUpState("aware0", false))
-        .WillOnce(testing::Return(true));
+    EXPECT_CALL(*iface_util_, setUpState("aware0", false)).WillOnce(testing::Return(true));
     removeIface(IfaceType::NAN, "aware0");
 }
 
 ////////// V1 Iface Combinations when AP creation is disabled //////////
 class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
-   public:
+  public:
     void SetUp() override {
         setupV1_AwareDisabledApIfaceCombination();
         WifiChipTest::SetUp();
     }
 };
 
-TEST_F(WifiChipV1_AwareDisabledApIfaceCombinationTest,
-       StaMode_CreateSta_ShouldSucceed) {
+TEST_F(WifiChipV1_AwareDisabledApIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     ASSERT_TRUE(createIface(IfaceType::AP).empty());
@@ -821,15 +771,14 @@
 
 ////////// V2 Iface Combinations when AP creation is disabled //////////
 class WifiChipV2_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
-   public:
+  public:
     void SetUp() override {
         setupV2_AwareDisabledApIfaceCombination();
         WifiChipTest::SetUp();
     }
 };
 
-TEST_F(WifiChipV2_AwareDisabledApIfaceCombinationTest,
-       CreateSta_ShouldSucceed) {
+TEST_F(WifiChipV2_AwareDisabledApIfaceCombinationTest, CreateSta_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     ASSERT_TRUE(createIface(IfaceType::AP).empty());
@@ -837,7 +786,7 @@
 
 ////////// Hypothetical Iface Combination with multiple ifaces //////////
 class WifiChip_MultiIfaceTest : public WifiChipTest {
-   public:
+  public:
     void SetUp() override {
         setup_MultiIfaceCombination();
         WifiChipTest::SetUp();
@@ -899,7 +848,7 @@
     ASSERT_EQ(createIface(IfaceType::STA), "wlan3");
 }
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/tests/wifi_iface_util_unit_tests.cpp b/wifi/1.6/default/tests/wifi_iface_util_unit_tests.cpp
similarity index 82%
rename from wifi/1.5/default/tests/wifi_iface_util_unit_tests.cpp
rename to wifi/1.6/default/tests/wifi_iface_util_unit_tests.cpp
index 8b67bb8..cc9a334 100644
--- a/wifi/1.5/default/tests/wifi_iface_util_unit_tests.cpp
+++ b/wifi/1.6/default/tests/wifi_iface_util_unit_tests.cpp
@@ -32,8 +32,7 @@
 constexpr uint8_t kMacAddress[] = {0x02, 0x12, 0x45, 0x56, 0xab, 0xcc};
 constexpr char kIfaceName[] = "test-wlan0";
 
-bool isValidUnicastLocallyAssignedMacAddress(
-    const std::array<uint8_t, 6>& mac_address) {
+bool isValidUnicastLocallyAssignedMacAddress(const std::array<uint8_t, 6>& mac_address) {
     uint8_t first_byte = mac_address[0];
     return (first_byte & 0x3) == kValidUnicastLocallyAssignedMacAddressMask;
 }
@@ -42,17 +41,16 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace iface_util {
 class WifiIfaceUtilTest : public Test {
-   protected:
+  protected:
     std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
-        new NiceMock<wifi_system::MockInterfaceTool>};
+            new NiceMock<wifi_system::MockInterfaceTool>};
     legacy_hal::wifi_hal_fn fake_func_table_;
     std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
-        new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_,
-                                                    fake_func_table_, true)};
+            new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_, fake_func_table_, true)};
     WifiIfaceUtil* iface_util_ = new WifiIfaceUtil(iface_tool_, legacy_hal_);
 };
 
@@ -67,20 +65,17 @@
 
 TEST_F(WifiIfaceUtilTest, IfaceEventHandlers_SetMacAddress) {
     std::array<uint8_t, 6> mac_address = {};
-    std::copy(std::begin(kMacAddress), std::end(kMacAddress),
-              std::begin(mac_address));
+    std::copy(std::begin(kMacAddress), std::end(kMacAddress), std::begin(mac_address));
     EXPECT_CALL(*iface_tool_, SetMacAddress(testing::_, testing::_))
-        .WillRepeatedly(testing::Return(true));
+            .WillRepeatedly(testing::Return(true));
     EXPECT_CALL(*iface_tool_, SetUpState(testing::_, testing::_))
-        .WillRepeatedly(testing::Return(true));
+            .WillRepeatedly(testing::Return(true));
 
     // Register for iface state toggle events.
     bool callback_invoked = false;
     iface_util::IfaceEventHandlers event_handlers = {};
     event_handlers.on_state_toggle_off_on =
-        [&callback_invoked](const std::string& /* iface_name */) {
-            callback_invoked = true;
-        };
+            [&callback_invoked](const std::string& /* iface_name */) { callback_invoked = true; };
     iface_util_->registerIfaceEventHandlers(kIfaceName, event_handlers);
     // Invoke setMacAddress and ensure that the cb is invoked.
     ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address));
@@ -95,7 +90,7 @@
 }
 }  // namespace iface_util
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.6/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.6/default/tests/wifi_nan_iface_unit_tests.cpp
new file mode 100644
index 0000000..c7c566b
--- /dev/null
+++ b/wifi/1.6/default/tests/wifi_nan_iface_unit_tests.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <cutils/properties.h>
+#include <gmock/gmock.h>
+
+#undef NAN  // This is weird, NAN is defined in bionic/libc/include/math.h:38
+#include "wifi_nan_iface.h"
+
+#include "mock_interface_tool.h"
+#include "mock_wifi_feature_flags.h"
+#include "mock_wifi_iface_util.h"
+#include "mock_wifi_legacy_hal.h"
+
+using testing::NiceMock;
+using testing::Return;
+using testing::Test;
+
+namespace {
+constexpr char kIfaceName[] = "mockWlan0";
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_6 {
+namespace implementation {
+
+using android::hardware::wifi::V1_2::NanDataPathConfirmInd;
+
+bool CaptureIfaceEventHandlers(const std::string& /* iface_name*/,
+                               iface_util::IfaceEventHandlers in_iface_event_handlers,
+                               iface_util::IfaceEventHandlers* out_iface_event_handlers) {
+    *out_iface_event_handlers = in_iface_event_handlers;
+    return true;
+}
+
+class MockNanIfaceEventCallback : public V1_5::IWifiNanIfaceEventCallback {
+  public:
+    MockNanIfaceEventCallback() = default;
+
+    MOCK_METHOD3(notifyCapabilitiesResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&,
+                              const android::hardware::wifi::V1_0::NanCapabilities&));
+    MOCK_METHOD2(notifyEnableResponse, Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyConfigResponse, Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyDisableResponse, Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD3(notifyStartPublishResponse, Return<void>(uint16_t, const WifiNanStatus&, uint8_t));
+    MOCK_METHOD2(notifyStopPublishResponse, Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD3(notifyStartSubscribeResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&, uint8_t));
+    MOCK_METHOD2(notifyStopSubscribeResponse, Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyTransmitFollowupResponse, Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyCreateDataInterfaceResponse, Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyDeleteDataInterfaceResponse, Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD3(notifyInitiateDataPathResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&, uint32_t));
+    MOCK_METHOD2(notifyRespondToDataPathIndicationResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyTerminateDataPathResponse, Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD1(eventClusterEvent, Return<void>(const NanClusterEventInd&));
+    MOCK_METHOD1(eventDisabled, Return<void>(const WifiNanStatus&));
+    MOCK_METHOD2(eventPublishTerminated, Return<void>(uint8_t, const WifiNanStatus&));
+    MOCK_METHOD2(eventSubscribeTerminated, Return<void>(uint8_t, const WifiNanStatus&));
+    MOCK_METHOD1(eventMatch, Return<void>(const NanMatchInd&));
+    MOCK_METHOD2(eventMatchExpired, Return<void>(uint8_t, uint32_t));
+    MOCK_METHOD1(eventFollowupReceived, Return<void>(const NanFollowupReceivedInd&));
+    MOCK_METHOD2(eventTransmitFollowup, Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD1(eventDataPathRequest, Return<void>(const NanDataPathRequestInd&));
+    MOCK_METHOD1(eventDataPathConfirm,
+                 Return<void>(const android::hardware::wifi::V1_0::NanDataPathConfirmInd&));
+    MOCK_METHOD1(eventDataPathTerminated, Return<void>(uint32_t));
+    MOCK_METHOD1(eventDataPathConfirm_1_2, Return<void>(const NanDataPathConfirmInd&));
+    MOCK_METHOD1(eventDataPathScheduleUpdate, Return<void>(const NanDataPathScheduleUpdateInd&));
+    MOCK_METHOD3(notifyCapabilitiesResponse_1_5,
+                 Return<void>(uint16_t, const WifiNanStatus&, const V1_5::NanCapabilities&));
+};
+
+class WifiNanIfaceTest : public Test {
+  protected:
+    legacy_hal::wifi_hal_fn fake_func_table_;
+    std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
+            new NiceMock<wifi_system::MockInterfaceTool>};
+    std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
+            new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_, fake_func_table_, true)};
+    std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
+            new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_, legacy_hal_)};
+};
+
+TEST_F(WifiNanIfaceTest, IfacEventHandlers_OnStateToggleOffOn) {
+    iface_util::IfaceEventHandlers captured_iface_event_handlers = {};
+    EXPECT_CALL(*legacy_hal_, nanRegisterCallbackHandlers(testing::_, testing::_))
+            .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+    EXPECT_CALL(*iface_util_, registerIfaceEventHandlers(testing::_, testing::_))
+            .WillOnce(testing::Invoke(bind(CaptureIfaceEventHandlers, std::placeholders::_1,
+                                           std::placeholders::_2, &captured_iface_event_handlers)));
+    sp<WifiNanIface> nan_iface = new WifiNanIface(kIfaceName, false, legacy_hal_, iface_util_);
+
+    // Register a mock nan event callback.
+    sp<NiceMock<MockNanIfaceEventCallback>> mock_event_callback{
+            new NiceMock<MockNanIfaceEventCallback>};
+    nan_iface->registerEventCallback(mock_event_callback, [](const WifiStatus& status) {
+        ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+    });
+    // Ensure that the eventDisabled() function in mock callback will be
+    // invoked.
+    WifiNanStatus expected_nan_status = {NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
+    EXPECT_CALL(*mock_event_callback, eventDisabled(expected_nan_status)).Times(1);
+
+    // Trigger the iface state toggle callback.
+    captured_iface_event_handlers.on_state_toggle_off_on(kIfaceName);
+}
+}  // namespace implementation
+}  // namespace V1_6
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.5/default/wifi.cpp b/wifi/1.6/default/wifi.cpp
similarity index 74%
rename from wifi/1.5/default/wifi.cpp
rename to wifi/1.6/default/wifi.cpp
index a85b242..c302ce2 100644
--- a/wifi/1.5/default/wifi.cpp
+++ b/wifi/1.6/default/wifi.cpp
@@ -28,16 +28,15 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 using hidl_return_util::validateAndCallWithLock;
 
-Wifi::Wifi(
-    const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
-    const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory,
-    const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
-    const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)
+Wifi::Wifi(const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
+           const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory,
+           const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
+           const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)
     : iface_tool_(iface_tool),
       legacy_hal_factory_(legacy_hal_factory),
       mode_controller_(mode_controller),
@@ -49,46 +48,44 @@
     return true;
 }
 
-Return<void> Wifi::registerEventCallback(
-    const sp<V1_0::IWifiEventCallback>& event_callback,
-    registerEventCallback_cb hidl_status_cb) {
+Return<void> Wifi::registerEventCallback(const sp<V1_0::IWifiEventCallback>& event_callback,
+                                         registerEventCallback_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
-                           &Wifi::registerEventCallbackInternal, hidl_status_cb,
+                           &Wifi::registerEventCallbackInternal, hidl_status_cb, event_callback);
+}
+
+Return<void> Wifi::registerEventCallback_1_5(const sp<V1_5::IWifiEventCallback>& event_callback,
+                                             registerEventCallback_1_5_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
+                           &Wifi::registerEventCallbackInternal_1_5, hidl_status_cb,
                            event_callback);
 }
 
-Return<void> Wifi::registerEventCallback_1_5(
-    const sp<V1_5::IWifiEventCallback>& event_callback,
-    registerEventCallback_1_5_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
-                           &Wifi::registerEventCallbackInternal_1_5,
-                           hidl_status_cb, event_callback);
+Return<bool> Wifi::isStarted() {
+    return run_state_ != RunState::STOPPED;
 }
 
-Return<bool> Wifi::isStarted() { return run_state_ != RunState::STOPPED; }
-
 Return<void> Wifi::start(start_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
-                           &Wifi::startInternal, hidl_status_cb);
+    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal,
+                           hidl_status_cb);
 }
 
 Return<void> Wifi::stop(stop_cb hidl_status_cb) {
-    return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN,
-                                   &Wifi::stopInternal, hidl_status_cb);
+    return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal,
+                                   hidl_status_cb);
 }
 
 Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
-                           &Wifi::getChipIdsInternal, hidl_status_cb);
+    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipIdsInternal,
+                           hidl_status_cb);
 }
 
 Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
-                           &Wifi::getChipInternal, hidl_status_cb, chip_id);
+    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipInternal,
+                           hidl_status_cb, chip_id);
 }
 
-Return<void> Wifi::debug(const hidl_handle& handle,
-                         const hidl_vec<hidl_string>&) {
+Return<void> Wifi::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) {
     LOG(INFO) << "-----------Debug is called----------------";
     if (chips_.size() == 0) {
         return Void();
@@ -103,13 +100,13 @@
 }
 
 WifiStatus Wifi::registerEventCallbackInternal(
-    const sp<V1_0::IWifiEventCallback>& event_callback __unused) {
+        const sp<V1_0::IWifiEventCallback>& event_callback __unused) {
     // Deprecated support for this callback.
     return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
 }
 
 WifiStatus Wifi::registerEventCallbackInternal_1_5(
-    const sp<V1_5::IWifiEventCallback>& event_callback) {
+        const sp<V1_5::IWifiEventCallback>& event_callback) {
     if (!event_cb_handler_.addCallback(event_callback)) {
         return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
     }
@@ -120,36 +117,32 @@
     if (run_state_ == RunState::STARTED) {
         return createWifiStatus(WifiStatusCode::SUCCESS);
     } else if (run_state_ == RunState::STOPPING) {
-        return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
-                                "HAL is stopping");
+        return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping");
     }
     WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
     if (wifi_status.code == WifiStatusCode::SUCCESS) {
         // Register the callback for subsystem restart
-        const auto& on_subsystem_restart_callback =
-            [this](const std::string& error) {
-                WifiStatus wifi_status =
-                    createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);
-                for (const auto& callback : event_cb_handler_.getCallbacks()) {
-                    LOG(INFO) << "Attempting to invoke onSubsystemRestart "
+        const auto& on_subsystem_restart_callback = [this](const std::string& error) {
+            WifiStatus wifi_status = createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);
+            for (const auto& callback : event_cb_handler_.getCallbacks()) {
+                LOG(INFO) << "Attempting to invoke onSubsystemRestart "
+                             "callback";
+                if (!callback->onSubsystemRestart(wifi_status).isOk()) {
+                    LOG(ERROR) << "Failed to invoke onSubsystemRestart callback";
+                } else {
+                    LOG(INFO) << "Succeeded to invoke onSubsystemRestart "
                                  "callback";
-                    if (!callback->onSubsystemRestart(wifi_status).isOk()) {
-                        LOG(ERROR)
-                            << "Failed to invoke onSubsystemRestart callback";
-                    } else {
-                        LOG(INFO) << "Succeeded to invoke onSubsystemRestart "
-                                     "callback";
-                    }
                 }
-            };
+            }
+        };
 
         // Create the chip instance once the HAL is started.
         android::hardware::wifi::V1_0::ChipId chipId = kPrimaryChipId;
         for (auto& hal : legacy_hals_) {
-            chips_.push_back(new WifiChip(
-                chipId, chipId == kPrimaryChipId, hal, mode_controller_,
-                std::make_shared<iface_util::WifiIfaceUtil>(iface_tool_, hal),
-                feature_flags_, on_subsystem_restart_callback));
+            chips_.push_back(
+                    new WifiChip(chipId, chipId == kPrimaryChipId, hal, mode_controller_,
+                                 std::make_shared<iface_util::WifiIfaceUtil>(iface_tool_, hal),
+                                 feature_flags_, on_subsystem_restart_callback));
             chipId++;
         }
         run_state_ = RunState::STARTED;
@@ -173,12 +166,11 @@
 }
 
 WifiStatus Wifi::stopInternal(
-    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
+        /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
     if (run_state_ == RunState::STOPPED) {
         return createWifiStatus(WifiStatusCode::SUCCESS);
     } else if (run_state_ == RunState::STOPPING) {
-        return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
-                                "HAL is stopping");
+        return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping");
     }
     // Clear the chip object and its child objects since the HAL is now
     // stopped.
@@ -220,8 +212,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)};
 }
 
-std::pair<WifiStatus, sp<V1_4::IWifiChip>> Wifi::getChipInternal(
-    ChipId chip_id) {
+std::pair<WifiStatus, sp<V1_4::IWifiChip>> Wifi::getChipInternal(ChipId chip_id) {
     for (auto& chip : chips_) {
         ChipId cand_id = getChipIdFromWifiChip(chip);
         if ((cand_id != UINT32_MAX) && (cand_id == chip_id))
@@ -238,8 +229,7 @@
     }
 
     legacy_hals_ = legacy_hal_factory_->getHals();
-    if (legacy_hals_.empty())
-        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    if (legacy_hals_.empty()) return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
     int index = 0;  // for failure log
     for (auto& hal : legacy_hals_) {
         legacy_hal::wifi_error legacy_status = hal->initialize();
@@ -258,7 +248,7 @@
 }
 
 WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController(
-    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
+        /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
     legacy_hal::wifi_error legacy_status = legacy_hal::WIFI_SUCCESS;
     int index = 0;
 
@@ -298,7 +288,7 @@
     return chip_id;
 }
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi.h b/wifi/1.6/default/wifi.h
similarity index 79%
rename from wifi/1.5/default/wifi.h
rename to wifi/1.6/default/wifi.h
index c94ef3f..435358e 100644
--- a/wifi/1.5/default/wifi.h
+++ b/wifi/1.6/default/wifi.h
@@ -21,7 +21,7 @@
 // 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/hardware/wifi/1.6/IWifi.h>
 
 #include <android-base/macros.h>
 #include <utils/Looper.h>
@@ -37,46 +37,41 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 
 /**
  * Root HIDL interface object used to control the Wifi HAL.
  */
-class Wifi : public V1_5::IWifi {
-   public:
+class Wifi : public V1_6::IWifi {
+  public:
     Wifi(const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
-         const std::shared_ptr<legacy_hal::WifiLegacyHalFactory>
-             legacy_hal_factory,
-         const std::shared_ptr<mode_controller::WifiModeController>
-             mode_controller,
+         const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory,
+         const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
          const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags);
 
     bool isValid();
 
     // HIDL methods exposed.
-    Return<void> registerEventCallback(
-        const sp<V1_0::IWifiEventCallback>& event_callback,
-        registerEventCallback_cb hidl_status_cb) override;
-    Return<void> registerEventCallback_1_5(
-        const sp<V1_5::IWifiEventCallback>& event_callback,
-        registerEventCallback_1_5_cb hidl_status_cb) override;
+    Return<void> registerEventCallback(const sp<V1_0::IWifiEventCallback>& event_callback,
+                                       registerEventCallback_cb hidl_status_cb) override;
+    Return<void> registerEventCallback_1_5(const sp<V1_5::IWifiEventCallback>& event_callback,
+                                           registerEventCallback_1_5_cb hidl_status_cb) override;
     Return<bool> isStarted() override;
     Return<void> start(start_cb hidl_status_cb) override;
     Return<void> stop(stop_cb hidl_status_cb) override;
     Return<void> getChipIds(getChipIds_cb hidl_status_cb) override;
     Return<void> getChip(ChipId chip_id, getChip_cb hidl_status_cb) override;
-    Return<void> debug(const hidl_handle& handle,
-                       const hidl_vec<hidl_string>& options) override;
+    Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>& options) override;
 
-   private:
+  private:
     enum class RunState { STOPPED, STARTED, STOPPING };
 
     // Corresponding worker functions for the HIDL methods.
     WifiStatus registerEventCallbackInternal(
-        const sp<V1_0::IWifiEventCallback>& event_callback __unused);
+            const sp<V1_0::IWifiEventCallback>& event_callback __unused);
     WifiStatus registerEventCallbackInternal_1_5(
-        const sp<V1_5::IWifiEventCallback>& event_callback);
+            const sp<V1_5::IWifiEventCallback>& event_callback);
     WifiStatus startInternal();
     WifiStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock);
     std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
@@ -84,7 +79,7 @@
 
     WifiStatus initializeModeControllerAndLegacyHal();
     WifiStatus stopLegacyHalAndDeinitializeModeController(
-        std::unique_lock<std::recursive_mutex>* lock);
+            std::unique_lock<std::recursive_mutex>* lock);
     ChipId getChipIdFromWifiChip(sp<WifiChip>& chip);
 
     // Instance is created in this root level |IWifi| HIDL interface object
@@ -96,14 +91,13 @@
     std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
     RunState run_state_;
     std::vector<sp<WifiChip>> chips_;
-    hidl_callback_util::HidlCallbackHandler<V1_5::IWifiEventCallback>
-        event_cb_handler_;
+    hidl_callback_util::HidlCallbackHandler<V1_5::IWifiEventCallback> event_cb_handler_;
 
     DISALLOW_COPY_AND_ASSIGN(Wifi);
 };
 
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_ap_iface.cpp b/wifi/1.6/default/wifi_ap_iface.cpp
similarity index 75%
rename from wifi/1.5/default/wifi_ap_iface.cpp
rename to wifi/1.6/default/wifi_ap_iface.cpp
index 1ae7905..b2957db 100644
--- a/wifi/1.5/default/wifi_ap_iface.cpp
+++ b/wifi/1.6/default/wifi_ap_iface.cpp
@@ -24,14 +24,13 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 
-WifiApIface::WifiApIface(
-    const std::string& ifname, const std::vector<std::string>& instances,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
-    const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
+WifiApIface::WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
+                         const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+                         const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
     : ifname_(ifname),
       instances_(instances),
       legacy_hal_(legacy_hal),
@@ -43,14 +42,16 @@
     is_valid_ = false;
 }
 
-bool WifiApIface::isValid() { return is_valid_; }
+bool WifiApIface::isValid() {
+    return is_valid_;
+}
 
-std::string WifiApIface::getName() { return ifname_; }
+std::string WifiApIface::getName() {
+    return ifname_;
+}
 
 void WifiApIface::removeInstance(std::string instance) {
-    instances_.erase(
-        std::remove(instances_.begin(), instances_.end(), instance),
-        instances_.end());
+    instances_.erase(std::remove(instances_.begin(), instances_.end(), instance), instances_.end());
 }
 
 Return<void> WifiApIface::getName(getName_cb hidl_status_cb) {
@@ -66,44 +67,35 @@
 Return<void> WifiApIface::setCountryCode(const hidl_array<int8_t, 2>& code,
                                          setCountryCode_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiApIface::setCountryCodeInternal, hidl_status_cb,
-                           code);
+                           &WifiApIface::setCountryCodeInternal, hidl_status_cb, code);
 }
 
-Return<void> WifiApIface::getValidFrequenciesForBand(
-    V1_0::WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
+Return<void> WifiApIface::getValidFrequenciesForBand(V1_0::WifiBand band,
+                                                     getValidFrequenciesForBand_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiApIface::getValidFrequenciesForBandInternal,
-                           hidl_status_cb, band);
+                           &WifiApIface::getValidFrequenciesForBandInternal, hidl_status_cb, band);
 }
 
 Return<void> WifiApIface::setMacAddress(const hidl_array<uint8_t, 6>& mac,
                                         setMacAddress_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiApIface::setMacAddressInternal, hidl_status_cb,
-                           mac);
+                           &WifiApIface::setMacAddressInternal, hidl_status_cb, mac);
 }
 
-Return<void> WifiApIface::getFactoryMacAddress(
-    getFactoryMacAddress_cb hidl_status_cb) {
+Return<void> WifiApIface::getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiApIface::getFactoryMacAddressInternal,
-                           hidl_status_cb,
+                           &WifiApIface::getFactoryMacAddressInternal, hidl_status_cb,
                            instances_.size() > 0 ? instances_[0] : ifname_);
 }
 
-Return<void> WifiApIface::resetToFactoryMacAddress(
-    resetToFactoryMacAddress_cb hidl_status_cb) {
+Return<void> WifiApIface::resetToFactoryMacAddress(resetToFactoryMacAddress_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiApIface::resetToFactoryMacAddressInternal,
-                           hidl_status_cb);
+                           &WifiApIface::resetToFactoryMacAddressInternal, hidl_status_cb);
 }
 
-Return<void> WifiApIface::getBridgedInstances(
-    getBridgedInstances_cb hidl_status_cb) {
+Return<void> WifiApIface::getBridgedInstances(getBridgedInstances_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiApIface::getBridgedInstancesInternal,
-                           hidl_status_cb);
+                           &WifiApIface::getBridgedInstancesInternal, hidl_status_cb);
 }
 
 std::pair<WifiStatus, std::string> WifiApIface::getNameInternal() {
@@ -114,28 +106,24 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::AP};
 }
 
-WifiStatus WifiApIface::setCountryCodeInternal(
-    const std::array<int8_t, 2>& code) {
+WifiStatus WifiApIface::setCountryCodeInternal(const std::array<int8_t, 2>& code) {
     legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setCountryCode(
-        instances_.size() > 0 ? instances_[0] : ifname_, code);
+            instances_.size() > 0 ? instances_[0] : ifname_, code);
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
 WifiApIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) {
-    static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t),
-                  "Size mismatch");
+    static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch");
     legacy_hal::wifi_error legacy_status;
     std::vector<uint32_t> valid_frequencies;
-    std::tie(legacy_status, valid_frequencies) =
-        legacy_hal_.lock()->getValidFrequenciesForBand(
+    std::tie(legacy_status, valid_frequencies) = legacy_hal_.lock()->getValidFrequenciesForBand(
             instances_.size() > 0 ? instances_[0] : ifname_,
             hidl_struct_util::convertHidlWifiBandToLegacy(band));
     return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
 }
 
-WifiStatus WifiApIface::setMacAddressInternal(
-    const std::array<uint8_t, 6>& mac) {
+WifiStatus WifiApIface::setMacAddressInternal(const std::array<uint8_t, 6>& mac) {
     // Support random MAC up to 2 interfaces
     if (instances_.size() == 2) {
         int rbyte = 1;
@@ -160,12 +148,10 @@
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-std::pair<WifiStatus, std::array<uint8_t, 6>>
-WifiApIface::getFactoryMacAddressInternal(const std::string& ifaceName) {
-    std::array<uint8_t, 6> mac =
-        iface_util_.lock()->getFactoryMacAddress(ifaceName);
-    if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 &&
-        mac[4] == 0 && mac[5] == 0) {
+std::pair<WifiStatus, std::array<uint8_t, 6>> WifiApIface::getFactoryMacAddressInternal(
+        const std::string& ifaceName) {
+    std::array<uint8_t, 6> mac = iface_util_.lock()->getFactoryMacAddress(ifaceName);
+    if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0) {
         return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac};
     }
     return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
@@ -188,10 +174,9 @@
         // bridged interface even if we got the request to reset the Factory
         // MAC. Since the bridged interface is an internal interface for the
         // operation of bpf and others networking operation.
-        if (!iface_util_.lock()->setMacAddress(
-                ifname_, iface_util_.lock()->createRandomMacAddress())) {
-            LOG(ERROR) << "Fail to config MAC for bridged interface "
-                       << ifname_;
+        if (!iface_util_.lock()->setMacAddress(ifname_,
+                                               iface_util_.lock()->createRandomMacAddress())) {
+            LOG(ERROR) << "Fail to config MAC for bridged interface " << ifname_;
             return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
         }
     } else {
@@ -205,8 +190,7 @@
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-std::pair<WifiStatus, std::vector<hidl_string>>
-WifiApIface::getBridgedInstancesInternal() {
+std::pair<WifiStatus, std::vector<hidl_string>> WifiApIface::getBridgedInstancesInternal() {
     std::vector<hidl_string> instances;
     for (const auto& instance_name : instances_) {
         instances.push_back(instance_name);
@@ -214,7 +198,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), instances};
 }
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_ap_iface.h b/wifi/1.6/default/wifi_ap_iface.h
similarity index 75%
rename from wifi/1.5/default/wifi_ap_iface.h
rename to wifi/1.6/default/wifi_ap_iface.h
index 8f8387d..d1c0642 100644
--- a/wifi/1.5/default/wifi_ap_iface.h
+++ b/wifi/1.6/default/wifi_ap_iface.h
@@ -26,7 +26,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 
@@ -34,9 +34,8 @@
  * HIDL interface object used to control a AP Iface instance.
  */
 class WifiApIface : public V1_5::IWifiApIface {
-   public:
-    WifiApIface(const std::string& ifname,
-                const std::vector<std::string>& instances,
+  public:
+    WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
                 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
                 const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
     // Refer to |WifiChip::invalidate()|.
@@ -50,32 +49,27 @@
     Return<void> getType(getType_cb hidl_status_cb) override;
     Return<void> setCountryCode(const hidl_array<int8_t, 2>& code,
                                 setCountryCode_cb hidl_status_cb) override;
-    Return<void> getValidFrequenciesForBand(
-        V1_0::WifiBand band,
-        getValidFrequenciesForBand_cb hidl_status_cb) override;
+    Return<void> getValidFrequenciesForBand(V1_0::WifiBand band,
+                                            getValidFrequenciesForBand_cb hidl_status_cb) override;
     Return<void> setMacAddress(const hidl_array<uint8_t, 6>& mac,
                                setMacAddress_cb hidl_status_cb) override;
-    Return<void> getFactoryMacAddress(
-        getFactoryMacAddress_cb hidl_status_cb) override;
-    Return<void> resetToFactoryMacAddress(
-        resetToFactoryMacAddress_cb hidl_status_cb) override;
+    Return<void> getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) override;
+    Return<void> resetToFactoryMacAddress(resetToFactoryMacAddress_cb hidl_status_cb) override;
 
-    Return<void> getBridgedInstances(
-        getBridgedInstances_cb hidl_status_cb) override;
+    Return<void> getBridgedInstances(getBridgedInstances_cb hidl_status_cb) override;
 
-   private:
+  private:
     // Corresponding worker functions for the HIDL methods.
     std::pair<WifiStatus, std::string> getNameInternal();
     std::pair<WifiStatus, IfaceType> getTypeInternal();
     WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code);
-    std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-    getValidFrequenciesForBandInternal(V1_0::WifiBand band);
+    std::pair<WifiStatus, std::vector<WifiChannelInMhz>> getValidFrequenciesForBandInternal(
+            V1_0::WifiBand band);
     WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
     std::pair<WifiStatus, std::array<uint8_t, 6>> getFactoryMacAddressInternal(
-        const std::string& ifaceName);
+            const std::string& ifaceName);
     WifiStatus resetToFactoryMacAddressInternal();
-    std::pair<WifiStatus, std::vector<hidl_string>>
-    getBridgedInstancesInternal();
+    std::pair<WifiStatus, std::vector<hidl_string>> getBridgedInstancesInternal();
 
     std::string ifname_;
     std::vector<std::string> instances_;
@@ -87,7 +81,7 @@
 };
 
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.6/default/wifi_chip.cpp
similarity index 72%
rename from wifi/1.5/default/wifi_chip.cpp
rename to wifi/1.6/default/wifi_chip.cpp
index 6bdff42..c1ce766 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.6/default/wifi_chip.cpp
@@ -52,8 +52,7 @@
 template <typename Iface>
 void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
     iface->invalidate();
-    ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface),
-                 ifaces.end());
+    ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface), ifaces.end());
 }
 
 template <typename Iface>
@@ -74,8 +73,7 @@
 }
 
 template <typename Iface>
-sp<Iface> findUsingName(std::vector<sp<Iface>>& ifaces,
-                        const std::string& name) {
+sp<Iface> findUsingName(std::vector<sp<Iface>>& ifaces, const std::string& name) {
     std::vector<hidl_string> names;
     for (const auto& iface : ifaces) {
         if (name == iface->getName()) {
@@ -93,8 +91,7 @@
 
     std::array<char, PROPERTY_VALUE_MAX> buffer;
     if (idx == 0 || idx == 1) {
-        const char* altPropName =
-            (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface";
+        const char* altPropName = (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface";
         auto res = property_get(altPropName, buffer.data(), nullptr);
         if (res > 0) return buffer.data();
     }
@@ -111,15 +108,13 @@
     std::vector<std::string> ifnames;
     std::array<char, PROPERTY_VALUE_MAX> buffer;
     buffer.fill(0);
-    if (property_get("ro.vendor.wifi.sap.interface", buffer.data(), nullptr) ==
-        0) {
+    if (property_get("ro.vendor.wifi.sap.interface", buffer.data(), nullptr) == 0) {
         return ifnames;
     }
     ifnames.push_back(buffer.data());
     if (is_bridged) {
         buffer.fill(0);
-        if (property_get("ro.vendor.wifi.sap.concurrent.iface", buffer.data(),
-                         nullptr) == 0) {
+        if (property_get("ro.vendor.wifi.sap.concurrent.iface", buffer.data(), nullptr) == 0) {
             return ifnames;
         }
         ifnames.push_back(buffer.data());
@@ -133,29 +128,25 @@
     std::string p2pDevIfName = "";
     std::array<char, PROPERTY_VALUE_MAX> buffer;
     property_get("wifi.direct.interface", buffer.data(), "p2p0");
-    if (strncmp(buffer.data(), P2P_MGMT_DEVICE_PREFIX,
-                strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
+    if (strncmp(buffer.data(), P2P_MGMT_DEVICE_PREFIX, strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
         /* Get the p2p parent interface name from p2p device interface name set
          * in property */
         strncpy(p2pParentIfname, buffer.data() + strlen(P2P_MGMT_DEVICE_PREFIX),
                 strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX));
-        if (property_get(kActiveWlanIfaceNameProperty, primaryIfaceName.data(),
-                         nullptr) == 0) {
+        if (property_get(kActiveWlanIfaceNameProperty, primaryIfaceName.data(), nullptr) == 0) {
             return buffer.data();
         }
         /* Check if the parent interface derived from p2p device interface name
          * is active */
         if (strncmp(p2pParentIfname, primaryIfaceName.data(),
-                    strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX)) !=
-            0) {
+                    strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX)) != 0) {
             /*
              * Update the predefined p2p device interface parent interface name
              * with current active wlan interface
              */
             p2pDevIfName += P2P_MGMT_DEVICE_PREFIX;
             p2pDevIfName += primaryIfaceName.data();
-            LOG(INFO) << "update the p2p device interface name to "
-                      << p2pDevIfName.c_str();
+            LOG(INFO) << "update the p2p device interface name to " << p2pDevIfName.c_str();
             return p2pDevIfName;
         }
     }
@@ -184,8 +175,7 @@
 bool removeOldFilesInternal() {
     time_t now = time(0);
     const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds;
-    std::unique_ptr<DIR, decltype(&closedir)> dir_dump(
-        opendir(kTombstoneFolderPath), closedir);
+    std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(kTombstoneFolderPath), closedir);
     if (!dir_dump) {
         PLOG(ERROR) << "Failed to open directory";
         return false;
@@ -206,15 +196,13 @@
             continue;
         }
         const time_t cur_file_time = cur_file_stat.st_mtime;
-        valid_files.push_back(
-            std::pair<const time_t, std::string>(cur_file_time, cur_file_path));
+        valid_files.push_back(std::pair<const time_t, std::string>(cur_file_time, cur_file_path));
     }
     valid_files.sort();  // sort the list of files by last modified time from
                          // small to big.
     uint32_t cur_file_count = valid_files.size();
     for (auto cur_file : valid_files) {
-        if (cur_file_count > kMaxRingBufferFileNum ||
-            cur_file.first < delete_files_before) {
+        if (cur_file_count > kMaxRingBufferFileNum || cur_file.first < delete_files_before) {
             if (unlink(cur_file.second.c_str()) != 0) {
                 PLOG(ERROR) << "Error deleting file";
                 success = false;
@@ -228,17 +216,14 @@
 }
 
 // Helper function for |cpioArchiveFilesInDir|
-bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name,
-                     size_t file_name_len) {
+bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name, size_t file_name_len) {
     std::array<char, 32 * 1024> read_buf;
     ssize_t llen =
-        sprintf(read_buf.data(),
-                "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
-                kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid,
-                st.st_gid, static_cast<int>(st.st_nlink),
-                static_cast<int>(st.st_mtime), static_cast<int>(st.st_size),
-                major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
-                minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
+            sprintf(read_buf.data(), "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
+                    kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid, st.st_gid,
+                    static_cast<int>(st.st_nlink), static_cast<int>(st.st_mtime),
+                    static_cast<int>(st.st_size), major(st.st_dev), minor(st.st_dev),
+                    major(st.st_rdev), minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
     if (write(out_fd, read_buf.data(), llen) == -1) {
         PLOG(ERROR) << "Error writing cpio header to file " << file_name;
         return false;
@@ -300,9 +285,7 @@
     std::array<char, 4096> read_buf;
     read_buf.fill(0);
     if (write(out_fd, read_buf.data(),
-              sprintf(read_buf.data(), "070701%040X%056X%08XTRAILER!!!", 1,
-                      0x0b, 0) +
-                  4) == -1) {
+              sprintf(read_buf.data(), "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0) + 4) == -1) {
         PLOG(ERROR) << "Error writing trailing bytes";
         return false;
     }
@@ -315,8 +298,7 @@
 size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
     struct dirent* dp;
     size_t n_error = 0;
-    std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir),
-                                                       closedir);
+    std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir), closedir);
     if (!dir_dump) {
         PLOG(ERROR) << "Failed to open directory";
         return ++n_error;
@@ -340,14 +322,12 @@
             continue;
         }
         std::string file_name_with_last_modified_time =
-            cur_file_name + "-" + std::to_string(st.st_mtime);
+                cur_file_name + "-" + std::to_string(st.st_mtime);
         // string.size() does not include the null terminator. The cpio FreeBSD
         // file header expects the null character to be included in the length.
-        const size_t file_name_len =
-            file_name_with_last_modified_time.size() + 1;
+        const size_t file_name_len = file_name_with_last_modified_time.size() + 1;
         unique_fd file_auto_closer(fd_read);
-        if (!cpioWriteHeader(out_fd, st,
-                             file_name_with_last_modified_time.c_str(),
+        if (!cpioWriteHeader(out_fd, st, file_name_with_last_modified_time.c_str(),
                              file_name_len)) {
             return ++n_error;
         }
@@ -375,18 +355,17 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 using hidl_return_util::validateAndCallWithLock;
 
-WifiChip::WifiChip(
-    ChipId chip_id, bool is_primary,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
-    const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
-    const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
-    const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
-    const std::function<void(const std::string&)>& handler)
+WifiChip::WifiChip(ChipId chip_id, bool is_primary,
+                   const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+                   const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
+                   const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
+                   const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
+                   const std::function<void(const std::string&)>& handler)
     : chip_id_(chip_id),
       legacy_hal_(legacy_hal),
       mode_controller_(mode_controller),
@@ -410,24 +389,25 @@
     is_valid_ = false;
 }
 
-bool WifiChip::isValid() { return is_valid_; }
+bool WifiChip::isValid() {
+    return is_valid_;
+}
 
 std::set<sp<V1_4::IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
     return event_cb_handler_.getCallbacks();
 }
 
 Return<void> WifiChip::getId(getId_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::getIdInternal, hidl_status_cb);
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::getIdInternal,
+                           hidl_status_cb);
 }
 
 // Deprecated support for this callback
-Return<void> WifiChip::registerEventCallback(
-    const sp<V1_0::IWifiChipEventCallback>& event_callback,
-    registerEventCallback_cb hidl_status_cb) {
+Return<void> WifiChip::registerEventCallback(const sp<V1_0::IWifiChipEventCallback>& event_callback,
+                                             registerEventCallback_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::registerEventCallbackInternal,
-                           hidl_status_cb, event_callback);
+                           &WifiChip::registerEventCallbackInternal, hidl_status_cb,
+                           event_callback);
 }
 
 Return<void> WifiChip::getCapabilities(getCapabilities_cb hidl_status_cb) {
@@ -437,15 +417,12 @@
 
 Return<void> WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::getAvailableModesInternal,
-                           hidl_status_cb);
+                           &WifiChip::getAvailableModesInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::configureChip(ChipModeId mode_id,
-                                     configureChip_cb hidl_status_cb) {
-    return validateAndCallWithLock(
-        this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-        &WifiChip::configureChipInternal, hidl_status_cb, mode_id);
+Return<void> WifiChip::configureChip(ChipModeId mode_id, configureChip_cb hidl_status_cb) {
+    return validateAndCallWithLock(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                                   &WifiChip::configureChipInternal, hidl_status_cb, mode_id);
 }
 
 Return<void> WifiChip::getMode(getMode_cb hidl_status_cb) {
@@ -453,25 +430,19 @@
                            &WifiChip::getModeInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::requestChipDebugInfo(
-    requestChipDebugInfo_cb hidl_status_cb) {
+Return<void> WifiChip::requestChipDebugInfo(requestChipDebugInfo_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::requestChipDebugInfoInternal,
-                           hidl_status_cb);
+                           &WifiChip::requestChipDebugInfoInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::requestDriverDebugDump(
-    requestDriverDebugDump_cb hidl_status_cb) {
+Return<void> WifiChip::requestDriverDebugDump(requestDriverDebugDump_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::requestDriverDebugDumpInternal,
-                           hidl_status_cb);
+                           &WifiChip::requestDriverDebugDumpInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::requestFirmwareDebugDump(
-    requestFirmwareDebugDump_cb hidl_status_cb) {
+Return<void> WifiChip::requestFirmwareDebugDump(requestFirmwareDebugDump_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::requestFirmwareDebugDumpInternal,
-                           hidl_status_cb);
+                           &WifiChip::requestFirmwareDebugDumpInternal, hidl_status_cb);
 }
 
 Return<void> WifiChip::createApIface(createApIface_cb hidl_status_cb) {
@@ -479,11 +450,9 @@
                            &WifiChip::createApIfaceInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::createBridgedApIface(
-    createBridgedApIface_cb hidl_status_cb) {
+Return<void> WifiChip::createBridgedApIface(createBridgedApIface_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::createBridgedApIfaceInternal,
-                           hidl_status_cb);
+                           &WifiChip::createBridgedApIfaceInternal, hidl_status_cb);
 }
 
 Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) {
@@ -491,27 +460,22 @@
                            &WifiChip::getApIfaceNamesInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::getApIface(const hidl_string& ifname,
-                                  getApIface_cb hidl_status_cb) {
+Return<void> WifiChip::getApIface(const hidl_string& ifname, getApIface_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::getApIfaceInternal, hidl_status_cb,
-                           ifname);
+                           &WifiChip::getApIfaceInternal, hidl_status_cb, ifname);
 }
 
-Return<void> WifiChip::removeApIface(const hidl_string& ifname,
-                                     removeApIface_cb hidl_status_cb) {
+Return<void> WifiChip::removeApIface(const hidl_string& ifname, removeApIface_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::removeApIfaceInternal, hidl_status_cb,
-                           ifname);
+                           &WifiChip::removeApIfaceInternal, hidl_status_cb, ifname);
 }
 
 Return<void> WifiChip::removeIfaceInstanceFromBridgedApIface(
-    const hidl_string& ifname, const hidl_string& ifInstanceName,
-    removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) {
-    return validateAndCall(
-        this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-        &WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal,
-        hidl_status_cb, ifname, ifInstanceName);
+        const hidl_string& ifname, const hidl_string& ifInstanceName,
+        removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal, hidl_status_cb,
+                           ifname, ifInstanceName);
 }
 
 Return<void> WifiChip::createNanIface(createNanIface_cb hidl_status_cb) {
@@ -524,18 +488,14 @@
                            &WifiChip::getNanIfaceNamesInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::getNanIface(const hidl_string& ifname,
-                                   getNanIface_cb hidl_status_cb) {
+Return<void> WifiChip::getNanIface(const hidl_string& ifname, getNanIface_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::getNanIfaceInternal, hidl_status_cb,
-                           ifname);
+                           &WifiChip::getNanIfaceInternal, hidl_status_cb, ifname);
 }
 
-Return<void> WifiChip::removeNanIface(const hidl_string& ifname,
-                                      removeNanIface_cb hidl_status_cb) {
+Return<void> WifiChip::removeNanIface(const hidl_string& ifname, removeNanIface_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::removeNanIfaceInternal, hidl_status_cb,
-                           ifname);
+                           &WifiChip::removeNanIfaceInternal, hidl_status_cb, ifname);
 }
 
 Return<void> WifiChip::createP2pIface(createP2pIface_cb hidl_status_cb) {
@@ -548,18 +508,14 @@
                            &WifiChip::getP2pIfaceNamesInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::getP2pIface(const hidl_string& ifname,
-                                   getP2pIface_cb hidl_status_cb) {
+Return<void> WifiChip::getP2pIface(const hidl_string& ifname, getP2pIface_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::getP2pIfaceInternal, hidl_status_cb,
-                           ifname);
+                           &WifiChip::getP2pIfaceInternal, hidl_status_cb, ifname);
 }
 
-Return<void> WifiChip::removeP2pIface(const hidl_string& ifname,
-                                      removeP2pIface_cb hidl_status_cb) {
+Return<void> WifiChip::removeP2pIface(const hidl_string& ifname, removeP2pIface_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::removeP2pIfaceInternal, hidl_status_cb,
-                           ifname);
+                           &WifiChip::removeP2pIfaceInternal, hidl_status_cb, ifname);
 }
 
 Return<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {
@@ -572,132 +528,106 @@
                            &WifiChip::getStaIfaceNamesInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::getStaIface(const hidl_string& ifname,
-                                   getStaIface_cb hidl_status_cb) {
+Return<void> WifiChip::getStaIface(const hidl_string& ifname, getStaIface_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::getStaIfaceInternal, hidl_status_cb,
-                           ifname);
+                           &WifiChip::getStaIfaceInternal, hidl_status_cb, ifname);
 }
 
-Return<void> WifiChip::removeStaIface(const hidl_string& ifname,
-                                      removeStaIface_cb hidl_status_cb) {
+Return<void> WifiChip::removeStaIface(const hidl_string& ifname, removeStaIface_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::removeStaIfaceInternal, hidl_status_cb,
-                           ifname);
+                           &WifiChip::removeStaIfaceInternal, hidl_status_cb, ifname);
 }
 
-Return<void> WifiChip::createRttController(
-    const sp<IWifiIface>& bound_iface, createRttController_cb hidl_status_cb) {
+Return<void> WifiChip::createRttController(const sp<IWifiIface>& bound_iface,
+                                           createRttController_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::createRttControllerInternal,
-                           hidl_status_cb, bound_iface);
+                           &WifiChip::createRttControllerInternal, hidl_status_cb, bound_iface);
 }
 
-Return<void> WifiChip::getDebugRingBuffersStatus(
-    getDebugRingBuffersStatus_cb hidl_status_cb) {
+Return<void> WifiChip::getDebugRingBuffersStatus(getDebugRingBuffersStatus_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::getDebugRingBuffersStatusInternal,
-                           hidl_status_cb);
+                           &WifiChip::getDebugRingBuffersStatusInternal, hidl_status_cb);
 }
 
 Return<void> WifiChip::startLoggingToDebugRingBuffer(
-    const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
-    uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes,
-    startLoggingToDebugRingBuffer_cb hidl_status_cb) {
+        const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
+        uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes,
+        startLoggingToDebugRingBuffer_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::startLoggingToDebugRingBufferInternal,
-                           hidl_status_cb, ring_name, verbose_level,
-                           max_interval_in_sec, min_data_size_in_bytes);
+                           &WifiChip::startLoggingToDebugRingBufferInternal, hidl_status_cb,
+                           ring_name, verbose_level, max_interval_in_sec, min_data_size_in_bytes);
 }
 
-Return<void> WifiChip::forceDumpToDebugRingBuffer(
-    const hidl_string& ring_name,
-    forceDumpToDebugRingBuffer_cb hidl_status_cb) {
+Return<void> WifiChip::forceDumpToDebugRingBuffer(const hidl_string& ring_name,
+                                                  forceDumpToDebugRingBuffer_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::forceDumpToDebugRingBufferInternal,
-                           hidl_status_cb, ring_name);
+                           &WifiChip::forceDumpToDebugRingBufferInternal, hidl_status_cb,
+                           ring_name);
 }
 
-Return<void> WifiChip::flushRingBufferToFile(
-    flushRingBufferToFile_cb hidl_status_cb) {
+Return<void> WifiChip::flushRingBufferToFile(flushRingBufferToFile_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::flushRingBufferToFileInternal,
-                           hidl_status_cb);
+                           &WifiChip::flushRingBufferToFileInternal, hidl_status_cb);
 }
 
 Return<void> WifiChip::stopLoggingToDebugRingBuffer(
-    stopLoggingToDebugRingBuffer_cb hidl_status_cb) {
+        stopLoggingToDebugRingBuffer_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::stopLoggingToDebugRingBufferInternal,
-                           hidl_status_cb);
+                           &WifiChip::stopLoggingToDebugRingBufferInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::getDebugHostWakeReasonStats(
-    getDebugHostWakeReasonStats_cb hidl_status_cb) {
+Return<void> WifiChip::getDebugHostWakeReasonStats(getDebugHostWakeReasonStats_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::getDebugHostWakeReasonStatsInternal,
-                           hidl_status_cb);
+                           &WifiChip::getDebugHostWakeReasonStatsInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::enableDebugErrorAlerts(
-    bool enable, enableDebugErrorAlerts_cb hidl_status_cb) {
+Return<void> WifiChip::enableDebugErrorAlerts(bool enable,
+                                              enableDebugErrorAlerts_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::enableDebugErrorAlertsInternal,
-                           hidl_status_cb, enable);
+                           &WifiChip::enableDebugErrorAlertsInternal, hidl_status_cb, enable);
 }
 
-Return<void> WifiChip::selectTxPowerScenario(
-    V1_1::IWifiChip::TxPowerScenario scenario,
-    selectTxPowerScenario_cb hidl_status_cb) {
+Return<void> WifiChip::selectTxPowerScenario(V1_1::IWifiChip::TxPowerScenario scenario,
+                                             selectTxPowerScenario_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::selectTxPowerScenarioInternal,
-                           hidl_status_cb, scenario);
+                           &WifiChip::selectTxPowerScenarioInternal, hidl_status_cb, scenario);
 }
 
-Return<void> WifiChip::resetTxPowerScenario(
-    resetTxPowerScenario_cb hidl_status_cb) {
+Return<void> WifiChip::resetTxPowerScenario(resetTxPowerScenario_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::resetTxPowerScenarioInternal,
-                           hidl_status_cb);
+                           &WifiChip::resetTxPowerScenarioInternal, hidl_status_cb);
 }
 
-Return<void> WifiChip::setLatencyMode(LatencyMode mode,
-                                      setLatencyMode_cb hidl_status_cb) {
+Return<void> WifiChip::setLatencyMode(LatencyMode mode, setLatencyMode_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::setLatencyModeInternal, hidl_status_cb,
-                           mode);
+                           &WifiChip::setLatencyModeInternal, hidl_status_cb, mode);
 }
 
 Return<void> WifiChip::registerEventCallback_1_2(
-    const sp<V1_2::IWifiChipEventCallback>& event_callback,
-    registerEventCallback_cb hidl_status_cb) {
+        const sp<V1_2::IWifiChipEventCallback>& event_callback,
+        registerEventCallback_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::registerEventCallbackInternal_1_2,
-                           hidl_status_cb, event_callback);
+                           &WifiChip::registerEventCallbackInternal_1_2, hidl_status_cb,
+                           event_callback);
 }
 
-Return<void> WifiChip::selectTxPowerScenario_1_2(
-    TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) {
+Return<void> WifiChip::selectTxPowerScenario_1_2(TxPowerScenario scenario,
+                                                 selectTxPowerScenario_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::selectTxPowerScenarioInternal_1_2,
-                           hidl_status_cb, scenario);
+                           &WifiChip::selectTxPowerScenarioInternal_1_2, hidl_status_cb, scenario);
 }
 
 Return<void> WifiChip::getCapabilities_1_3(getCapabilities_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::getCapabilitiesInternal_1_3,
-                           hidl_status_cb);
+                           &WifiChip::getCapabilitiesInternal_1_3, hidl_status_cb);
 }
 
-Return<void> WifiChip::getCapabilities_1_5(
-    getCapabilities_1_5_cb hidl_status_cb) {
+Return<void> WifiChip::getCapabilities_1_5(getCapabilities_1_5_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::getCapabilitiesInternal_1_5,
-                           hidl_status_cb);
+                           &WifiChip::getCapabilitiesInternal_1_5, hidl_status_cb);
 }
 
-Return<void> WifiChip::debug(const hidl_handle& handle,
-                             const hidl_vec<hidl_string>&) {
+Return<void> WifiChip::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) {
     if (handle != nullptr && handle->numFds >= 1) {
         {
             std::unique_lock<std::mutex> lk(lock_t);
@@ -723,66 +653,58 @@
     return Void();
 }
 
-Return<void> WifiChip::createRttController_1_4(
-    const sp<IWifiIface>& bound_iface,
-    createRttController_1_4_cb hidl_status_cb) {
+Return<void> WifiChip::createRttController_1_4(const sp<IWifiIface>& bound_iface,
+                                               createRttController_1_4_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::createRttControllerInternal_1_4,
-                           hidl_status_cb, bound_iface);
+                           &WifiChip::createRttControllerInternal_1_4, hidl_status_cb, bound_iface);
 }
 
 Return<void> WifiChip::registerEventCallback_1_4(
-    const sp<V1_4::IWifiChipEventCallback>& event_callback,
-    registerEventCallback_cb hidl_status_cb) {
+        const sp<V1_4::IWifiChipEventCallback>& event_callback,
+        registerEventCallback_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::registerEventCallbackInternal_1_4,
-                           hidl_status_cb, event_callback);
+                           &WifiChip::registerEventCallbackInternal_1_4, hidl_status_cb,
+                           event_callback);
 }
 
 Return<void> WifiChip::setMultiStaPrimaryConnection(
-    const hidl_string& ifname, setMultiStaPrimaryConnection_cb hidl_status_cb) {
+        const hidl_string& ifname, setMultiStaPrimaryConnection_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::setMultiStaPrimaryConnectionInternal,
-                           hidl_status_cb, ifname);
+                           &WifiChip::setMultiStaPrimaryConnectionInternal, hidl_status_cb, ifname);
 }
 
-Return<void> WifiChip::setMultiStaUseCase(
-    MultiStaUseCase use_case, setMultiStaUseCase_cb hidl_status_cb) {
+Return<void> WifiChip::setMultiStaUseCase(MultiStaUseCase use_case,
+                                          setMultiStaUseCase_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::setMultiStaUseCaseInternal,
-                           hidl_status_cb, use_case);
+                           &WifiChip::setMultiStaUseCaseInternal, hidl_status_cb, use_case);
 }
 
-Return<void> WifiChip::setCoexUnsafeChannels(
-    const hidl_vec<CoexUnsafeChannel>& unsafeChannels,
-    hidl_bitfield<CoexRestriction> restrictions,
-    setCoexUnsafeChannels_cb hidl_status_cb) {
+Return<void> WifiChip::setCoexUnsafeChannels(const hidl_vec<CoexUnsafeChannel>& unsafeChannels,
+                                             hidl_bitfield<CoexRestriction> restrictions,
+                                             setCoexUnsafeChannels_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::setCoexUnsafeChannelsInternal,
-                           hidl_status_cb, unsafeChannels, restrictions);
+                           &WifiChip::setCoexUnsafeChannelsInternal, hidl_status_cb, unsafeChannels,
+                           restrictions);
 }
 
 Return<void> WifiChip::setCountryCode(const hidl_array<int8_t, 2>& code,
                                       setCountryCode_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiChip::setCountryCodeInternal, hidl_status_cb,
-                           code);
+                           &WifiChip::setCountryCodeInternal, hidl_status_cb, code);
 }
 
 Return<void> WifiChip::getUsableChannels(
-    WifiBand band, hidl_bitfield<WifiIfaceMode> ifaceModeMask,
-    hidl_bitfield<UsableChannelFilter> filterMask,
-    getUsableChannels_cb _hidl_cb) {
+        WifiBand band, hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask,
+        hidl_bitfield<V1_5::IWifiChip::UsableChannelFilter> filterMask,
+        getUsableChannels_cb _hidl_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::getUsableChannelsInternal, _hidl_cb, band,
-                           ifaceModeMask, filterMask);
+                           &WifiChip::getUsableChannelsInternal, _hidl_cb, band, ifaceModeMask,
+                           filterMask);
 }
 
-Return<void> WifiChip::triggerSubsystemRestart(
-    triggerSubsystemRestart_cb hidl_status_cb) {
+Return<void> WifiChip::triggerSubsystemRestart(triggerSubsystemRestart_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::triggerSubsystemRestartInternal,
-                           hidl_status_cb);
+                           &WifiChip::triggerSubsystemRestartInternal, hidl_status_cb);
 }
 
 void WifiChip::invalidateAndRemoveAllIfaces() {
@@ -799,16 +721,13 @@
     rtt_controllers_.clear();
 }
 
-void WifiChip::invalidateAndRemoveDependencies(
-    const std::string& removed_iface_name) {
+void WifiChip::invalidateAndRemoveDependencies(const std::string& removed_iface_name) {
     for (auto it = nan_ifaces_.begin(); it != nan_ifaces_.end();) {
         auto nan_iface = *it;
         if (nan_iface->getName() == removed_iface_name) {
             nan_iface->invalidate();
             for (const auto& callback : event_cb_handler_.getCallbacks()) {
-                if (!callback
-                         ->onIfaceRemoved(IfaceType::NAN, removed_iface_name)
-                         .isOk()) {
+                if (!callback->onIfaceRemoved(IfaceType::NAN, removed_iface_name).isOk()) {
                     LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
                 }
             }
@@ -834,7 +753,7 @@
 }
 
 WifiStatus WifiChip::registerEventCallbackInternal(
-    const sp<V1_0::IWifiChipEventCallback>& /* event_callback */) {
+        const sp<V1_0::IWifiChipEventCallback>& /* event_callback */) {
     // Deprecated support for this callback.
     return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
 }
@@ -850,8 +769,7 @@
 }
 
 WifiStatus WifiChip::configureChipInternal(
-    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
-    ChipModeId mode_id) {
+        /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id) {
     if (!isValidModeId(mode_id)) {
         return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
     }
@@ -863,8 +781,7 @@
     if (status.code != WifiStatusCode::SUCCESS) {
         for (const auto& callback : event_cb_handler_.getCallbacks()) {
             if (!callback->onChipReconfigureFailure(status).isOk()) {
-                LOG(ERROR)
-                    << "Failed to invoke onChipReconfigureFailure callback";
+                LOG(ERROR) << "Failed to invoke onChipReconfigureFailure callback";
             }
         }
         return status;
@@ -878,45 +795,38 @@
     LOG(INFO) << "Configured chip in mode " << mode_id;
     setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
 
-    legacy_hal_.lock()->registerSubsystemRestartCallbackHandler(
-        subsystemCallbackHandler_);
+    legacy_hal_.lock()->registerSubsystemRestartCallbackHandler(subsystemCallbackHandler_);
 
     return status;
 }
 
 std::pair<WifiStatus, uint32_t> WifiChip::getModeInternal() {
     if (!isValidModeId(current_mode_id_)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE),
-                current_mode_id_};
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), current_mode_id_};
     }
     return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_};
 }
 
-std::pair<WifiStatus, V1_4::IWifiChip::ChipDebugInfo>
-WifiChip::requestChipDebugInfoInternal() {
+std::pair<WifiStatus, V1_4::IWifiChip::ChipDebugInfo> WifiChip::requestChipDebugInfoInternal() {
     V1_4::IWifiChip::ChipDebugInfo result;
     legacy_hal::wifi_error legacy_status;
     std::string driver_desc;
     const auto ifname = getFirstActiveWlanIfaceName();
-    std::tie(legacy_status, driver_desc) =
-        legacy_hal_.lock()->getDriverVersion(ifname);
+    std::tie(legacy_status, driver_desc) = legacy_hal_.lock()->getDriverVersion(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to get driver version: "
-                   << legacyErrorToString(legacy_status);
-        WifiStatus status = createWifiStatusFromLegacyError(
-            legacy_status, "failed to get driver version");
+        LOG(ERROR) << "Failed to get driver version: " << legacyErrorToString(legacy_status);
+        WifiStatus status =
+                createWifiStatusFromLegacyError(legacy_status, "failed to get driver version");
         return {status, result};
     }
     result.driverDescription = driver_desc.c_str();
 
     std::string firmware_desc;
-    std::tie(legacy_status, firmware_desc) =
-        legacy_hal_.lock()->getFirmwareVersion(ifname);
+    std::tie(legacy_status, firmware_desc) = legacy_hal_.lock()->getFirmwareVersion(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to get firmware version: "
-                   << legacyErrorToString(legacy_status);
-        WifiStatus status = createWifiStatusFromLegacyError(
-            legacy_status, "failed to get firmware version");
+        LOG(ERROR) << "Failed to get firmware version: " << legacyErrorToString(legacy_status);
+        WifiStatus status =
+                createWifiStatusFromLegacyError(legacy_status, "failed to get firmware version");
         return {status, result};
     }
     result.firmwareDescription = firmware_desc.c_str();
@@ -924,32 +834,25 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), result};
 }
 
-std::pair<WifiStatus, std::vector<uint8_t>>
-WifiChip::requestDriverDebugDumpInternal() {
+std::pair<WifiStatus, std::vector<uint8_t>> WifiChip::requestDriverDebugDumpInternal() {
     legacy_hal::wifi_error legacy_status;
     std::vector<uint8_t> driver_dump;
     std::tie(legacy_status, driver_dump) =
-        legacy_hal_.lock()->requestDriverMemoryDump(
-            getFirstActiveWlanIfaceName());
+            legacy_hal_.lock()->requestDriverMemoryDump(getFirstActiveWlanIfaceName());
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to get driver debug dump: "
-                   << legacyErrorToString(legacy_status);
-        return {createWifiStatusFromLegacyError(legacy_status),
-                std::vector<uint8_t>()};
+        LOG(ERROR) << "Failed to get driver debug dump: " << legacyErrorToString(legacy_status);
+        return {createWifiStatusFromLegacyError(legacy_status), std::vector<uint8_t>()};
     }
     return {createWifiStatus(WifiStatusCode::SUCCESS), driver_dump};
 }
 
-std::pair<WifiStatus, std::vector<uint8_t>>
-WifiChip::requestFirmwareDebugDumpInternal() {
+std::pair<WifiStatus, std::vector<uint8_t>> WifiChip::requestFirmwareDebugDumpInternal() {
     legacy_hal::wifi_error legacy_status;
     std::vector<uint8_t> firmware_dump;
     std::tie(legacy_status, firmware_dump) =
-        legacy_hal_.lock()->requestFirmwareMemoryDump(
-            getFirstActiveWlanIfaceName());
+            legacy_hal_.lock()->requestFirmwareMemoryDump(getFirstActiveWlanIfaceName());
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to get firmware debug dump: "
-                   << legacyErrorToString(legacy_status);
+        LOG(ERROR) << "Failed to get firmware debug dump: " << legacyErrorToString(legacy_status);
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
     return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump};
@@ -958,8 +861,7 @@
 WifiStatus WifiChip::createVirtualApInterface(const std::string& apVirtIf) {
     legacy_hal::wifi_error legacy_status;
     legacy_status = legacy_hal_.lock()->createVirtualInterface(
-        apVirtIf,
-        hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
+            apVirtIf, hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to add interface: " << apVirtIf << " "
                    << legacyErrorToString(legacy_status);
@@ -975,8 +877,7 @@
             ap_instances = it.second;
         }
     }
-    sp<WifiApIface> iface =
-        new WifiApIface(ifname, ap_instances, legacy_hal_, iface_util_);
+    sp<WifiApIface> iface = new WifiApIface(ifname, ap_instances, legacy_hal_, iface_util_);
     ap_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
         if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
@@ -987,8 +888,7 @@
     return iface;
 }
 
-std::pair<WifiStatus, sp<V1_5::IWifiApIface>>
-WifiChip::createApIfaceInternal() {
+std::pair<WifiStatus, sp<V1_5::IWifiApIface>> WifiChip::createApIfaceInternal() {
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
@@ -1001,8 +901,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
 }
 
-std::pair<WifiStatus, sp<V1_5::IWifiApIface>>
-WifiChip::createBridgedApIfaceInternal() {
+std::pair<WifiStatus, sp<V1_5::IWifiApIface>> WifiChip::createBridgedApIfaceInternal() {
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
@@ -1018,7 +917,7 @@
             if (i != 0) {  // The failure happened when creating second virtual
                            // iface.
                 legacy_hal_.lock()->deleteVirtualInterface(
-                    ap_instances.front());  // Remove the first virtual iface.
+                        ap_instances.front());  // Remove the first virtual iface.
             }
             return {status, {}};
         }
@@ -1032,8 +931,7 @@
     for (auto const& instance : ap_instances) {
         // Bind ap instance interface to AP bridge
         if (!iface_util_->addIfaceToBridge(br_ifname, instance)) {
-            LOG(ERROR) << "Failed add if to Bridge - if_name="
-                       << instance.c_str();
+            LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str();
             invalidateAndClearBridgedAp(br_ifname);
             return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
         }
@@ -1042,8 +940,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
 }
 
-std::pair<WifiStatus, std::vector<hidl_string>>
-WifiChip::getApIfaceNamesInternal() {
+std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getApIfaceNamesInternal() {
     if (ap_ifaces_.empty()) {
         return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
     }
@@ -1051,7 +948,7 @@
 }
 
 std::pair<WifiStatus, sp<V1_5::IWifiApIface>> WifiChip::getApIfaceInternal(
-    const std::string& ifname) {
+        const std::string& ifname) {
     const auto iface = findUsingName(ap_ifaces_, ifname);
     if (!iface.get()) {
         return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
@@ -1082,7 +979,7 @@
 }
 
 WifiStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal(
-    const std::string& ifname, const std::string& ifInstanceName) {
+        const std::string& ifname, const std::string& ifInstanceName) {
     const auto iface = findUsingName(ap_ifaces_, ifname);
     if (!iface.get() || ifInstanceName.empty()) {
         return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
@@ -1094,23 +991,20 @@
             for (auto const& iface : ap_instances) {
                 if (iface == ifInstanceName) {
                     if (!iface_util_->removeIfaceFromBridge(it.first, iface)) {
-                        LOG(ERROR)
-                            << "Failed to remove interface: " << ifInstanceName
-                            << " from " << ifname;
-                        return createWifiStatus(
-                            WifiStatusCode::ERROR_NOT_AVAILABLE);
+                        LOG(ERROR) << "Failed to remove interface: " << ifInstanceName << " from "
+                                   << ifname;
+                        return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE);
                     }
                     legacy_hal::wifi_error legacy_status =
-                        legacy_hal_.lock()->deleteVirtualInterface(iface);
+                            legacy_hal_.lock()->deleteVirtualInterface(iface);
                     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-                        LOG(ERROR) << "Failed to del interface: " << iface
-                                   << " " << legacyErrorToString(legacy_status);
+                        LOG(ERROR) << "Failed to del interface: " << iface << " "
+                                   << legacyErrorToString(legacy_status);
                         return createWifiStatusFromLegacyError(legacy_status);
                     }
                     ap_instances.erase(
-                        std::remove(ap_instances.begin(), ap_instances.end(),
-                                    ifInstanceName),
-                        ap_instances.end());
+                            std::remove(ap_instances.begin(), ap_instances.end(), ifInstanceName),
+                            ap_instances.end());
                     br_ifaces_ap_instances_[ifname] = ap_instances;
                     break;
                 }
@@ -1124,8 +1018,7 @@
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-std::pair<WifiStatus, sp<V1_4::IWifiNanIface>>
-WifiChip::createNanIfaceInternal() {
+std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> WifiChip::createNanIfaceInternal() {
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
@@ -1137,8 +1030,7 @@
         ifname = getFirstActiveWlanIfaceName();
         is_dedicated_iface = false;
     }
-    sp<WifiNanIface> iface =
-        new WifiNanIface(ifname, is_dedicated_iface, legacy_hal_, iface_util_);
+    sp<WifiNanIface> iface = new WifiNanIface(ifname, is_dedicated_iface, legacy_hal_, iface_util_);
     nan_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
         if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
@@ -1148,8 +1040,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
 }
 
-std::pair<WifiStatus, std::vector<hidl_string>>
-WifiChip::getNanIfaceNamesInternal() {
+std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getNanIfaceNamesInternal() {
     if (nan_ifaces_.empty()) {
         return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
     }
@@ -1157,7 +1048,7 @@
 }
 
 std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> WifiChip::getNanIfaceInternal(
-    const std::string& ifname) {
+        const std::string& ifname) {
     const auto iface = findUsingName(nan_ifaces_, ifname);
     if (!iface.get()) {
         return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
@@ -1194,16 +1085,14 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
 }
 
-std::pair<WifiStatus, std::vector<hidl_string>>
-WifiChip::getP2pIfaceNamesInternal() {
+std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getP2pIfaceNamesInternal() {
     if (p2p_ifaces_.empty()) {
         return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
     }
     return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(p2p_ifaces_)};
 }
 
-std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::getP2pIfaceInternal(
-    const std::string& ifname) {
+std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::getP2pIfaceInternal(const std::string& ifname) {
     const auto iface = findUsingName(p2p_ifaces_, ifname);
     if (!iface.get()) {
         return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
@@ -1225,16 +1114,13 @@
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-std::pair<WifiStatus, sp<V1_5::IWifiStaIface>>
-WifiChip::createStaIfaceInternal() {
+std::pair<WifiStatus, sp<V1_5::IWifiStaIface>> WifiChip::createStaIfaceInternal() {
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::STA)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
     std::string ifname = allocateStaIfaceName();
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->createVirtualInterface(
-            ifname,
-            hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::STA));
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->createVirtualInterface(
+            ifname, hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::STA));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to add interface: " << ifname << " "
                    << legacyErrorToString(legacy_status);
@@ -1251,8 +1137,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
 }
 
-std::pair<WifiStatus, std::vector<hidl_string>>
-WifiChip::getStaIfaceNamesInternal() {
+std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getStaIfaceNamesInternal() {
     if (sta_ifaces_.empty()) {
         return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
     }
@@ -1260,7 +1145,7 @@
 }
 
 std::pair<WifiStatus, sp<V1_5::IWifiStaIface>> WifiChip::getStaIfaceInternal(
-    const std::string& ifname) {
+        const std::string& ifname) {
     const auto iface = findUsingName(sta_ifaces_, ifname);
     if (!iface.get()) {
         return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
@@ -1275,8 +1160,7 @@
     }
     // Invalidate & remove any dependent objects first.
     invalidateAndRemoveDependencies(ifname);
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->deleteVirtualInterface(ifname);
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->deleteVirtualInterface(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to remove interface: " << ifname << " "
                    << legacyErrorToString(legacy_status);
@@ -1291,8 +1175,8 @@
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-std::pair<WifiStatus, sp<V1_0::IWifiRttController>>
-WifiChip::createRttControllerInternal(const sp<IWifiIface>& /*bound_iface*/) {
+std::pair<WifiStatus, sp<V1_0::IWifiRttController>> WifiChip::createRttControllerInternal(
+        const sp<IWifiIface>& /*bound_iface*/) {
     LOG(ERROR) << "createRttController is not supported on this HAL";
     return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
 }
@@ -1300,38 +1184,33 @@
 std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
 WifiChip::getDebugRingBuffersStatusInternal() {
     legacy_hal::wifi_error legacy_status;
-    std::vector<legacy_hal::wifi_ring_buffer_status>
-        legacy_ring_buffer_status_vec;
+    std::vector<legacy_hal::wifi_ring_buffer_status> legacy_ring_buffer_status_vec;
     std::tie(legacy_status, legacy_ring_buffer_status_vec) =
-        legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName());
+            legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName());
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
     std::vector<WifiDebugRingBufferStatus> hidl_ring_buffer_status_vec;
     if (!hidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToHidl(
-            legacy_ring_buffer_status_vec, &hidl_ring_buffer_status_vec)) {
+                legacy_ring_buffer_status_vec, &hidl_ring_buffer_status_vec)) {
         return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
     }
-    return {createWifiStatus(WifiStatusCode::SUCCESS),
-            hidl_ring_buffer_status_vec};
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_ring_buffer_status_vec};
 }
 
 WifiStatus WifiChip::startLoggingToDebugRingBufferInternal(
-    const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
-    uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes) {
+        const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
+        uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes) {
     WifiStatus status = registerDebugRingBufferCallback();
     if (status.code != WifiStatusCode::SUCCESS) {
         return status;
     }
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->startRingBufferLogging(
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRingBufferLogging(
             getFirstActiveWlanIfaceName(), ring_name,
-            static_cast<
-                std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
-                verbose_level),
+            static_cast<std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(verbose_level),
             max_interval_in_sec, min_data_size_in_bytes);
-    ringbuffer_map_.insert(std::pair<std::string, Ringbuffer>(
-        ring_name, Ringbuffer(kMaxBufferSizeBytes)));
+    ringbuffer_map_.insert(
+            std::pair<std::string, Ringbuffer>(ring_name, Ringbuffer(kMaxBufferSizeBytes)));
     // if verbose logging enabled, turn up HAL daemon logging as well.
     if (verbose_level < WifiDebugRingBufferVerboseLevel::VERBOSE) {
         android::base::SetMinimumLogSeverity(android::base::DEBUG);
@@ -1341,15 +1220,13 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
-WifiStatus WifiChip::forceDumpToDebugRingBufferInternal(
-    const hidl_string& ring_name) {
+WifiStatus WifiChip::forceDumpToDebugRingBufferInternal(const hidl_string& ring_name) {
     WifiStatus status = registerDebugRingBufferCallback();
     if (status.code != WifiStatusCode::SUCCESS) {
         return status;
     }
     legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->getRingBufferData(getFirstActiveWlanIfaceName(),
-                                              ring_name);
+            legacy_hal_.lock()->getRingBufferData(getFirstActiveWlanIfaceName(), ring_name);
 
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1364,8 +1241,7 @@
 
 WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
     legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->deregisterRingBufferCallbackHandler(
-            getFirstActiveWlanIfaceName());
+            legacy_hal_.lock()->deregisterRingBufferCallbackHandler(getFirstActiveWlanIfaceName());
     if (legacy_status == legacy_hal::WIFI_SUCCESS) {
         debug_ring_buffer_cb_registered_ = false;
     }
@@ -1377,13 +1253,12 @@
     legacy_hal::wifi_error legacy_status;
     legacy_hal::WakeReasonStats legacy_stats;
     std::tie(legacy_status, legacy_stats) =
-        legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName());
+            legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName());
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
     WifiDebugHostWakeReasonStats hidl_stats;
-    if (!hidl_struct_util::convertLegacyWakeReasonStatsToHidl(legacy_stats,
-                                                              &hidl_stats)) {
+    if (!hidl_struct_util::convertLegacyWakeReasonStatsToHidl(legacy_stats, &hidl_stats)) {
         return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
     }
     return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
@@ -1393,62 +1268,56 @@
     legacy_hal::wifi_error legacy_status;
     if (enable) {
         android::wp<WifiChip> weak_ptr_this(this);
-        const auto& on_alert_callback = [weak_ptr_this](
-                                            int32_t error_code,
-                                            std::vector<uint8_t> debug_data) {
+        const auto& on_alert_callback = [weak_ptr_this](int32_t error_code,
+                                                        std::vector<uint8_t> debug_data) {
             const auto shared_ptr_this = weak_ptr_this.promote();
             if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
                 LOG(ERROR) << "Callback invoked on an invalid object";
                 return;
             }
             for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->onDebugErrorAlert(error_code, debug_data)
-                         .isOk()) {
+                if (!callback->onDebugErrorAlert(error_code, debug_data).isOk()) {
                     LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback";
                 }
             }
         };
         legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
-            getFirstActiveWlanIfaceName(), on_alert_callback);
+                getFirstActiveWlanIfaceName(), on_alert_callback);
     } else {
         legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
-            getFirstActiveWlanIfaceName());
+                getFirstActiveWlanIfaceName());
     }
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
-WifiStatus WifiChip::selectTxPowerScenarioInternal(
-    V1_1::IWifiChip::TxPowerScenario scenario) {
+WifiStatus WifiChip::selectTxPowerScenarioInternal(V1_1::IWifiChip::TxPowerScenario scenario) {
     auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
-        getFirstActiveWlanIfaceName(),
-        hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
+            getFirstActiveWlanIfaceName(),
+            hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::resetTxPowerScenarioInternal() {
-    auto legacy_status =
-        legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName());
+    auto legacy_status = legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName());
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) {
     auto legacy_status = legacy_hal_.lock()->setLatencyMode(
-        getFirstActiveWlanIfaceName(),
-        hidl_struct_util::convertHidlLatencyModeToLegacy(mode));
+            getFirstActiveWlanIfaceName(), hidl_struct_util::convertHidlLatencyModeToLegacy(mode));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::registerEventCallbackInternal_1_2(
-    const sp<V1_2::IWifiChipEventCallback>& /* event_callback */) {
+        const sp<V1_2::IWifiChipEventCallback>& /* event_callback */) {
     // Deprecated support for this callback.
     return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
 }
 
-WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(
-    TxPowerScenario scenario) {
+WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario) {
     auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
-        getFirstActiveWlanIfaceName(),
-        hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario));
+            getFirstActiveWlanIfaceName(),
+            hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1463,65 +1332,61 @@
     uint32_t legacy_logger_feature_set;
     const auto ifname = getFirstActiveWlanIfaceName();
     std::tie(legacy_status, legacy_feature_set) =
-        legacy_hal_.lock()->getSupportedFeatureSet(ifname);
+            legacy_hal_.lock()->getSupportedFeatureSet(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), 0};
     }
     std::tie(legacy_status, legacy_logger_feature_set) =
-        legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname);
+            legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         // some devices don't support querying logger feature set
         legacy_logger_feature_set = 0;
     }
     uint32_t hidl_caps;
     if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(
-            legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
+                legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
         return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
     }
     return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
 }
 
-std::pair<WifiStatus, sp<V1_4::IWifiRttController>>
-WifiChip::createRttControllerInternal_1_4(const sp<IWifiIface>& bound_iface) {
-    if (sta_ifaces_.size() == 0 &&
-        !canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
-        LOG(ERROR)
-            << "createRttControllerInternal_1_4: Chip cannot support STAs "
-               "(and RTT by extension)";
+std::pair<WifiStatus, sp<V1_4::IWifiRttController>> WifiChip::createRttControllerInternal_1_4(
+        const sp<IWifiIface>& bound_iface) {
+    if (sta_ifaces_.size() == 0 && !canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
+        LOG(ERROR) << "createRttControllerInternal_1_4: Chip cannot support STAs "
+                      "(and RTT by extension)";
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
-    sp<WifiRttController> rtt = new WifiRttController(
-        getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_);
+    sp<WifiRttController> rtt =
+            new WifiRttController(getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_);
     rtt_controllers_.emplace_back(rtt);
     return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
 }
 
 WifiStatus WifiChip::registerEventCallbackInternal_1_4(
-    const sp<V1_4::IWifiChipEventCallback>& event_callback) {
+        const sp<V1_4::IWifiChipEventCallback>& event_callback) {
     if (!event_cb_handler_.addCallback(event_callback)) {
         return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
     }
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-WifiStatus WifiChip::setMultiStaPrimaryConnectionInternal(
-    const std::string& ifname) {
-    auto legacy_status =
-        legacy_hal_.lock()->multiStaSetPrimaryConnection(ifname);
+WifiStatus WifiChip::setMultiStaPrimaryConnectionInternal(const std::string& ifname) {
+    auto legacy_status = legacy_hal_.lock()->multiStaSetPrimaryConnection(ifname);
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::setMultiStaUseCaseInternal(MultiStaUseCase use_case) {
     auto legacy_status = legacy_hal_.lock()->multiStaSetUseCase(
-        hidl_struct_util::convertHidlMultiStaUseCaseToLegacy(use_case));
+            hidl_struct_util::convertHidlMultiStaUseCaseToLegacy(use_case));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
-WifiStatus WifiChip::setCoexUnsafeChannelsInternal(
-    std::vector<CoexUnsafeChannel> unsafe_channels, uint32_t restrictions) {
+WifiStatus WifiChip::setCoexUnsafeChannelsInternal(std::vector<CoexUnsafeChannel> unsafe_channels,
+                                                   uint32_t restrictions) {
     std::vector<legacy_hal::wifi_coex_unsafe_channel> legacy_unsafe_channels;
-    if (!hidl_struct_util::convertHidlVectorOfCoexUnsafeChannelToLegacy(
-            unsafe_channels, &legacy_unsafe_channels)) {
+    if (!hidl_struct_util::convertHidlVectorOfCoexUnsafeChannelToLegacy(unsafe_channels,
+                                                                        &legacy_unsafe_channels)) {
         return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
     }
     uint32_t legacy_restrictions = 0;
@@ -1534,35 +1399,31 @@
     if (restrictions & CoexRestriction::WIFI_AWARE) {
         legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_AWARE;
     }
-    auto legacy_status = legacy_hal_.lock()->setCoexUnsafeChannels(
-        legacy_unsafe_channels, legacy_restrictions);
+    auto legacy_status =
+            legacy_hal_.lock()->setCoexUnsafeChannels(legacy_unsafe_channels, legacy_restrictions);
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::setCountryCodeInternal(const std::array<int8_t, 2>& code) {
-    auto legacy_status =
-        legacy_hal_.lock()->setCountryCode(getFirstActiveWlanIfaceName(), code);
+    auto legacy_status = legacy_hal_.lock()->setCountryCode(getFirstActiveWlanIfaceName(), code);
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
-std::pair<WifiStatus, std::vector<WifiUsableChannel>>
-WifiChip::getUsableChannelsInternal(WifiBand band, uint32_t ifaceModeMask,
-                                    uint32_t filterMask) {
+std::pair<WifiStatus, std::vector<WifiUsableChannel>> WifiChip::getUsableChannelsInternal(
+        WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask) {
     legacy_hal::wifi_error legacy_status;
     std::vector<legacy_hal::wifi_usable_channel> legacy_usable_channels;
-    std::tie(legacy_status, legacy_usable_channels) =
-        legacy_hal_.lock()->getUsableChannels(
+    std::tie(legacy_status, legacy_usable_channels) = legacy_hal_.lock()->getUsableChannels(
             hidl_struct_util::convertHidlWifiBandToLegacyMacBand(band),
             hidl_struct_util::convertHidlWifiIfaceModeToLegacy(ifaceModeMask),
-            hidl_struct_util::convertHidlUsableChannelFilterToLegacy(
-                filterMask));
+            hidl_struct_util::convertHidlUsableChannelFilterToLegacy(filterMask));
 
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
     std::vector<WifiUsableChannel> hidl_usable_channels;
-    if (!hidl_struct_util::convertLegacyWifiUsableChannelsToHidl(
-            legacy_usable_channels, &hidl_usable_channels)) {
+    if (!hidl_struct_util::convertLegacyWifiUsableChannelsToHidl(legacy_usable_channels,
+                                                                 &hidl_usable_channels)) {
         return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
     }
     return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_usable_channels};
@@ -1574,19 +1435,15 @@
 }
 
 WifiStatus WifiChip::handleChipConfiguration(
-    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
-    ChipModeId mode_id) {
+        /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id) {
     // If the chip is already configured in a different mode, stop
     // the legacy HAL and then start it after firmware mode change.
     if (isValidModeId(current_mode_id_)) {
-        LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_
-                  << " to mode " << mode_id;
+        LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_ << " to mode " << mode_id;
         invalidateAndRemoveAllIfaces();
-        legacy_hal::wifi_error legacy_status =
-            legacy_hal_.lock()->stop(lock, []() {});
+        legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stop(lock, []() {});
         if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-            LOG(ERROR) << "Failed to stop legacy HAL: "
-                       << legacyErrorToString(legacy_status);
+            LOG(ERROR) << "Failed to stop legacy HAL: " << legacyErrorToString(legacy_status);
             return createWifiStatusFromLegacyError(legacy_status);
         }
     }
@@ -1602,8 +1459,7 @@
     }
     legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to start legacy HAL: "
-                   << legacyErrorToString(legacy_status);
+        LOG(ERROR) << "Failed to start legacy HAL: " << legacyErrorToString(legacy_status);
         return createWifiStatusFromLegacyError(legacy_status);
     }
     // Every time the HAL is restarted, we need to register the
@@ -1619,8 +1475,7 @@
     if (WifiStatusCode::SUCCESS == version_info.first.code) {
         property_set("vendor.wlan.firmware.version",
                      version_info.second.firmwareDescription.c_str());
-        property_set("vendor.wlan.driver.version",
-                     version_info.second.driverDescription.c_str());
+        property_set("vendor.wlan.driver.version", version_info.second.driverDescription.c_str());
     }
 
     return createWifiStatus(WifiStatusCode::SUCCESS);
@@ -1633,36 +1488,33 @@
 
     android::wp<WifiChip> weak_ptr_this(this);
     const auto& on_ring_buffer_data_callback =
-        [weak_ptr_this](const std::string& name,
-                        const std::vector<uint8_t>& data,
-                        const legacy_hal::wifi_ring_buffer_status& status) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            WifiDebugRingBufferStatus hidl_status;
-            if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl(
-                    status, &hidl_status)) {
-                LOG(ERROR) << "Error converting ring buffer status";
-                return;
-            }
-            {
-                std::unique_lock<std::mutex> lk(shared_ptr_this->lock_t);
-                const auto& target =
-                    shared_ptr_this->ringbuffer_map_.find(name);
-                if (target != shared_ptr_this->ringbuffer_map_.end()) {
-                    Ringbuffer& cur_buffer = target->second;
-                    cur_buffer.append(data);
-                } else {
-                    LOG(ERROR) << "Ringname " << name << " not found";
+            [weak_ptr_this](const std::string& name, const std::vector<uint8_t>& data,
+                            const legacy_hal::wifi_ring_buffer_status& status) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
                     return;
                 }
-                // unique_lock unlocked here
-            }
-        };
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->registerRingBufferCallbackHandler(
+                WifiDebugRingBufferStatus hidl_status;
+                if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl(status,
+                                                                                &hidl_status)) {
+                    LOG(ERROR) << "Error converting ring buffer status";
+                    return;
+                }
+                {
+                    std::unique_lock<std::mutex> lk(shared_ptr_this->lock_t);
+                    const auto& target = shared_ptr_this->ringbuffer_map_.find(name);
+                    if (target != shared_ptr_this->ringbuffer_map_.end()) {
+                        Ringbuffer& cur_buffer = target->second;
+                        cur_buffer.append(data);
+                    } else {
+                        LOG(ERROR) << "Ringname " << name << " not found";
+                        return;
+                    }
+                    // unique_lock unlocked here
+                }
+            };
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->registerRingBufferCallbackHandler(
             getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback);
 
     if (legacy_status == legacy_hal::WIFI_SUCCESS) {
@@ -1674,35 +1526,32 @@
 WifiStatus WifiChip::registerRadioModeChangeCallback() {
     android::wp<WifiChip> weak_ptr_this(this);
     const auto& on_radio_mode_change_callback =
-        [weak_ptr_this](const std::vector<legacy_hal::WifiMacInfo>& mac_infos) {
-            const auto shared_ptr_this = weak_ptr_this.promote();
-            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-                LOG(ERROR) << "Callback invoked on an invalid object";
-                return;
-            }
-            std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>
-                hidl_radio_mode_infos;
-            if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl(
-                    mac_infos, &hidl_radio_mode_infos)) {
-                LOG(ERROR) << "Error converting wifi mac info";
-                return;
-            }
-            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->onRadioModeChange_1_4(hidl_radio_mode_infos)
-                         .isOk()) {
-                    LOG(ERROR) << "Failed to invoke onRadioModeChange_1_4"
-                               << " callback on: " << toString(callback);
+            [weak_ptr_this](const std::vector<legacy_hal::WifiMacInfo>& mac_infos) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
                 }
-            }
-        };
+                std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
+                if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl(mac_infos,
+                                                                       &hidl_radio_mode_infos)) {
+                    LOG(ERROR) << "Error converting wifi mac info";
+                    return;
+                }
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->onRadioModeChange_1_4(hidl_radio_mode_infos).isOk()) {
+                        LOG(ERROR) << "Failed to invoke onRadioModeChange_1_4"
+                                   << " callback on: " << toString(callback);
+                    }
+                }
+            };
     legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
-            getFirstActiveWlanIfaceName(), on_radio_mode_change_callback);
+            legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
+                    getFirstActiveWlanIfaceName(), on_radio_mode_change_callback);
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
-std::vector<V1_4::IWifiChip::ChipIfaceCombination>
-WifiChip::getCurrentModeIfaceCombinations() {
+std::vector<V1_4::IWifiChip::ChipIfaceCombination> WifiChip::getCurrentModeIfaceCombinations() {
     if (!isValidModeId(current_mode_id_)) {
         LOG(ERROR) << "Chip not configured in a mode yet";
         return {};
@@ -1732,7 +1581,7 @@
 // of ifaces of each type in the combination.
 // This method is a port of HalDeviceManager.expandIfaceCombos() from framework.
 std::vector<std::map<IfaceType, size_t>> WifiChip::expandIfaceCombinations(
-    const V1_4::IWifiChip::ChipIfaceCombination& combination) {
+        const V1_4::IWifiChip::ChipIfaceCombination& combination) {
     uint32_t num_expanded_combos = 1;
     for (const auto& limit : combination.limits) {
         for (uint32_t i = 0; i < limit.maxIfaces; i++) {
@@ -1745,8 +1594,7 @@
     std::vector<std::map<IfaceType, size_t>> expanded_combos;
     expanded_combos.resize(num_expanded_combos);
     for (auto& expanded_combo : expanded_combos) {
-        for (const auto type :
-             {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
+        for (const auto type : {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
             expanded_combo[type] = 0;
         }
     }
@@ -1755,8 +1603,7 @@
         for (uint32_t i = 0; i < limit.maxIfaces; i++) {
             span /= limit.types.size();
             for (uint32_t k = 0; k < num_expanded_combos; ++k) {
-                const auto iface_type =
-                    limit.types[(k / span) % limit.types.size()];
+                const auto iface_type = limit.types[(k / span) % limit.types.size()];
                 expanded_combos[k][iface_type]++;
             }
         }
@@ -1765,13 +1612,11 @@
 }
 
 bool WifiChip::canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(
-    const std::map<IfaceType, size_t>& expanded_combo,
-    IfaceType requested_type) {
+        const std::map<IfaceType, size_t>& expanded_combo, IfaceType requested_type) {
     const auto current_combo = getCurrentIfaceCombination();
 
     // Check if we have space for 1 more iface of |type| in this combo
-    for (const auto type :
-         {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
+    for (const auto type : {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
         size_t num_ifaces_needed = current_combo.at(type);
         if (type == requested_type) {
             num_ifaces_needed++;
@@ -1789,8 +1634,7 @@
 //    ChipIfaceCombination.
 // b) Check if the requested iface type can be added to the current mode
 //    with the iface combination that is already active.
-bool WifiChip::canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(
-    IfaceType requested_type) {
+bool WifiChip::canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType requested_type) {
     if (!isValidModeId(current_mode_id_)) {
         LOG(ERROR) << "Chip not configured in a mode yet";
         return false;
@@ -1799,8 +1643,8 @@
     for (const auto& combination : combinations) {
         const auto expanded_combos = expandIfaceCombinations(combination);
         for (const auto& expanded_combo : expanded_combos) {
-            if (canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(
-                    expanded_combo, requested_type)) {
+            if (canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(expanded_combo,
+                                                                         requested_type)) {
                 return true;
             }
         }
@@ -1811,11 +1655,10 @@
 // Note: This does not consider ifaces already active. It only checks if the
 // provided expanded iface combination can support the requested combo.
 bool WifiChip::canExpandedIfaceComboSupportIfaceCombo(
-    const std::map<IfaceType, size_t>& expanded_combo,
-    const std::map<IfaceType, size_t>& req_combo) {
+        const std::map<IfaceType, size_t>& expanded_combo,
+        const std::map<IfaceType, size_t>& req_combo) {
     // Check if we have space for 1 more iface of |type| in this combo
-    for (const auto type :
-         {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
+    for (const auto type : {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
         if (req_combo.count(type) == 0) {
             // Iface of "type" not in the req_combo.
             continue;
@@ -1834,8 +1677,7 @@
 // b) Check if the requested iface combo can be added to the current mode.
 // Note: This does not consider ifaces already active. It only checks if the
 // current mode can support the requested combo.
-bool WifiChip::canCurrentModeSupportIfaceCombo(
-    const std::map<IfaceType, size_t>& req_combo) {
+bool WifiChip::canCurrentModeSupportIfaceCombo(const std::map<IfaceType, size_t>& req_combo) {
     if (!isValidModeId(current_mode_id_)) {
         LOG(ERROR) << "Chip not configured in a mode yet";
         return false;
@@ -1844,8 +1686,7 @@
     for (const auto& combination : combinations) {
         const auto expanded_combos = expandIfaceCombinations(combination);
         for (const auto& expanded_combo : expanded_combos) {
-            if (canExpandedIfaceComboSupportIfaceCombo(expanded_combo,
-                                                       req_combo)) {
+            if (canExpandedIfaceComboSupportIfaceCombo(expanded_combo, req_combo)) {
                 return true;
             }
         }
@@ -1909,8 +1750,7 @@
 // Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx|
 // not already in use.
 // Note: This doesn't check the actual presence of these interfaces.
-std::string WifiChip::allocateApOrStaIfaceName(IfaceType type,
-                                               uint32_t start_idx) {
+std::string WifiChip::allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx) {
     for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) {
         const auto ifname = getWlanIfaceNameWithType(type, idx);
         if (findUsingNameFromBridgedApInstances(ifname)) continue;
@@ -1955,8 +1795,8 @@
     } else {
         int num_ifaces_need_to_allocate = 2 - instances.size();
         for (int i = 0; i < num_ifaces_need_to_allocate; i++) {
-            std::string instance_name = allocateApOrStaIfaceName(
-                IfaceType::AP, startIdxOfApIface() + i);
+            std::string instance_name =
+                    allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface() + i);
             if (!instance_name.empty()) {
                 instances.push_back(instance_name);
             }
@@ -1984,8 +1824,7 @@
             if (cur_buffer.getData().empty()) {
                 continue;
             }
-            const std::string file_path_raw =
-                kTombstoneFolderPath + item.first + "XXXXXXXXXX";
+            const std::string file_path_raw = kTombstoneFolderPath + item.first + "XXXXXXXXXX";
             const int dump_fd = mkstemp(makeCharVec(file_path_raw).data());
             if (dump_fd == -1) {
                 PLOG(ERROR) << "create file failed";
@@ -1993,8 +1832,8 @@
             }
             unique_fd file_auto_closer(dump_fd);
             for (const auto& cur_block : cur_buffer.getData()) {
-                if (write(dump_fd, cur_block.data(),
-                          sizeof(cur_block[0]) * cur_block.size()) == -1) {
+                if (write(dump_fd, cur_block.data(), sizeof(cur_block[0]) * cur_block.size()) ==
+                    -1) {
                     PLOG(ERROR) << "Error writing to file";
                 }
             }
@@ -2009,8 +1848,7 @@
     std::string ifname;
 
     // let the legacy hal override the interface name
-    legacy_hal::wifi_error err =
-        legacy_hal_.lock()->getSupportedIfaceName((uint32_t)type, ifname);
+    legacy_hal::wifi_error err = legacy_hal_.lock()->getSupportedIfaceName((uint32_t)type, ifname);
     if (err == legacy_hal::WIFI_SUCCESS) return ifname;
 
     return getWlanIfaceName(idx);
@@ -2059,7 +1897,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.6/default/wifi_chip.h b/wifi/1.6/default/wifi_chip.h
new file mode 100644
index 0000000..8a06898
--- /dev/null
+++ b/wifi/1.6/default/wifi_chip.h
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WIFI_CHIP_H_
+#define WIFI_CHIP_H_
+
+#include <list>
+#include <map>
+#include <mutex>
+
+#include <android-base/macros.h>
+#include <android/hardware/wifi/1.4/IWifiRttController.h>
+#include <android/hardware/wifi/1.5/IWifiChip.h>
+
+#include "hidl_callback_util.h"
+#include "ringbuffer.h"
+#include "wifi_ap_iface.h"
+#include "wifi_feature_flags.h"
+#include "wifi_legacy_hal.h"
+#include "wifi_mode_controller.h"
+#include "wifi_nan_iface.h"
+#include "wifi_p2p_iface.h"
+#include "wifi_rtt_controller.h"
+#include "wifi_sta_iface.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_6 {
+namespace implementation {
+using namespace android::hardware::wifi::V1_0;
+using V1_5::WifiBand;
+using V1_5::WifiUsableChannel;
+
+/**
+ * HIDL interface object used to control a Wifi HAL chip instance.
+ * Since there is only a single chip instance used today, there is no
+ * identifying handle information stored here.
+ */
+class WifiChip : public V1_5::IWifiChip {
+  public:
+    WifiChip(ChipId chip_id, bool is_primary,
+             const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+             const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
+             const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
+             const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
+             const std::function<void(const std::string&)>& subsystemCallbackHandler);
+    // HIDL does not provide a built-in mechanism to let the server invalidate
+    // a HIDL interface object after creation. If any client process holds onto
+    // a reference to the object in their context, any method calls on that
+    // reference will continue to be directed to the server.
+    //
+    // However Wifi HAL needs to control the lifetime of these objects. So, add
+    // a public |invalidate| method to |WifiChip| and it's child objects. This
+    // will be used to mark an object invalid when either:
+    // a) Wifi HAL is stopped, or
+    // b) Wifi Chip is reconfigured.
+    //
+    // All HIDL method implementations should check if the object is still
+    // marked valid before processing them.
+    void invalidate();
+    bool isValid();
+    std::set<sp<V1_4::IWifiChipEventCallback>> getEventCallbacks();
+
+    // HIDL methods exposed.
+    Return<void> getId(getId_cb hidl_status_cb) override;
+    // Deprecated support for this callback
+    Return<void> registerEventCallback(const sp<V1_0::IWifiChipEventCallback>& event_callback,
+                                       registerEventCallback_cb hidl_status_cb) override;
+    Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
+    Return<void> getAvailableModes(getAvailableModes_cb hidl_status_cb) override;
+    Return<void> configureChip(ChipModeId mode_id, configureChip_cb hidl_status_cb) override;
+    Return<void> getMode(getMode_cb hidl_status_cb) override;
+    Return<void> requestChipDebugInfo(requestChipDebugInfo_cb hidl_status_cb) override;
+    Return<void> requestDriverDebugDump(requestDriverDebugDump_cb hidl_status_cb) override;
+    Return<void> requestFirmwareDebugDump(requestFirmwareDebugDump_cb hidl_status_cb) override;
+    Return<void> createApIface(createApIface_cb hidl_status_cb) override;
+    Return<void> createBridgedApIface(createBridgedApIface_cb hidl_status_cb) override;
+    Return<void> getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override;
+    Return<void> getApIface(const hidl_string& ifname, getApIface_cb hidl_status_cb) override;
+    Return<void> removeApIface(const hidl_string& ifname, removeApIface_cb hidl_status_cb) override;
+    Return<void> removeIfaceInstanceFromBridgedApIface(
+            const hidl_string& brIfaceName, const hidl_string& ifaceInstanceName,
+            removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) override;
+    Return<void> createNanIface(createNanIface_cb hidl_status_cb) override;
+    Return<void> getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override;
+    Return<void> getNanIface(const hidl_string& ifname, getNanIface_cb hidl_status_cb) override;
+    Return<void> removeNanIface(const hidl_string& ifname,
+                                removeNanIface_cb hidl_status_cb) override;
+    Return<void> createP2pIface(createP2pIface_cb hidl_status_cb) override;
+    Return<void> getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) override;
+    Return<void> getP2pIface(const hidl_string& ifname, getP2pIface_cb hidl_status_cb) override;
+    Return<void> removeP2pIface(const hidl_string& ifname,
+                                removeP2pIface_cb hidl_status_cb) override;
+    Return<void> createStaIface(createStaIface_cb hidl_status_cb) override;
+    Return<void> getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) override;
+    Return<void> getStaIface(const hidl_string& ifname, getStaIface_cb hidl_status_cb) override;
+    Return<void> removeStaIface(const hidl_string& ifname,
+                                removeStaIface_cb hidl_status_cb) override;
+    Return<void> createRttController(const sp<IWifiIface>& bound_iface,
+                                     createRttController_cb hidl_status_cb) override;
+    Return<void> getDebugRingBuffersStatus(getDebugRingBuffersStatus_cb hidl_status_cb) override;
+    Return<void> startLoggingToDebugRingBuffer(
+            const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
+            uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes,
+            startLoggingToDebugRingBuffer_cb hidl_status_cb) override;
+    Return<void> forceDumpToDebugRingBuffer(const hidl_string& ring_name,
+                                            forceDumpToDebugRingBuffer_cb hidl_status_cb) override;
+    Return<void> flushRingBufferToFile(flushRingBufferToFile_cb hidl_status_cb) override;
+    Return<void> stopLoggingToDebugRingBuffer(
+            stopLoggingToDebugRingBuffer_cb hidl_status_cb) override;
+    Return<void> getDebugHostWakeReasonStats(
+            getDebugHostWakeReasonStats_cb hidl_status_cb) override;
+    Return<void> enableDebugErrorAlerts(bool enable,
+                                        enableDebugErrorAlerts_cb hidl_status_cb) override;
+    Return<void> selectTxPowerScenario(V1_1::IWifiChip::TxPowerScenario scenario,
+                                       selectTxPowerScenario_cb hidl_status_cb) override;
+    Return<void> resetTxPowerScenario(resetTxPowerScenario_cb hidl_status_cb) override;
+    Return<void> setLatencyMode(LatencyMode mode, setLatencyMode_cb hidl_status_cb) override;
+    Return<void> registerEventCallback_1_2(const sp<V1_2::IWifiChipEventCallback>& event_callback,
+                                           registerEventCallback_1_2_cb hidl_status_cb) override;
+    Return<void> selectTxPowerScenario_1_2(TxPowerScenario scenario,
+                                           selectTxPowerScenario_cb hidl_status_cb) override;
+    Return<void> getCapabilities_1_3(getCapabilities_cb hidl_status_cb) override;
+    Return<void> getCapabilities_1_5(getCapabilities_1_5_cb hidl_status_cb) override;
+    Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>& options) override;
+    Return<void> createRttController_1_4(const sp<IWifiIface>& bound_iface,
+                                         createRttController_1_4_cb hidl_status_cb) override;
+    Return<void> registerEventCallback_1_4(const sp<V1_4::IWifiChipEventCallback>& event_callback,
+                                           registerEventCallback_1_4_cb hidl_status_cb) override;
+    Return<void> setMultiStaPrimaryConnection(
+            const hidl_string& ifname, setMultiStaPrimaryConnection_cb hidl_status_cb) override;
+    Return<void> setMultiStaUseCase(MultiStaUseCase use_case,
+                                    setMultiStaUseCase_cb hidl_status_cb) override;
+    Return<void> setCoexUnsafeChannels(const hidl_vec<CoexUnsafeChannel>& unsafe_channels,
+                                       hidl_bitfield<IfaceType> restrictions,
+                                       setCoexUnsafeChannels_cb hidl_status_cb) override;
+    Return<void> setCountryCode(const hidl_array<int8_t, 2>& code,
+                                setCountryCode_cb _hidl_cb) override;
+    Return<void> getUsableChannels(WifiBand band, hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask,
+                                   hidl_bitfield<UsableChannelFilter> filterMask,
+                                   getUsableChannels_cb _hidl_cb) override;
+    Return<void> triggerSubsystemRestart(triggerSubsystemRestart_cb hidl_status_cb) override;
+
+  private:
+    void invalidateAndRemoveAllIfaces();
+    // When a STA iface is removed any dependent NAN-ifaces/RTT-controllers are
+    // invalidated & removed.
+    void invalidateAndRemoveDependencies(const std::string& removed_iface_name);
+
+    // Corresponding worker functions for the HIDL methods.
+    std::pair<WifiStatus, ChipId> getIdInternal();
+    // Deprecated support for this callback
+    WifiStatus registerEventCallbackInternal(
+            const sp<V1_0::IWifiChipEventCallback>& event_callback);
+    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
+    std::pair<WifiStatus, std::vector<ChipMode>> getAvailableModesInternal();
+    WifiStatus configureChipInternal(std::unique_lock<std::recursive_mutex>* lock,
+                                     ChipModeId mode_id);
+    std::pair<WifiStatus, uint32_t> getModeInternal();
+    std::pair<WifiStatus, IWifiChip::ChipDebugInfo> requestChipDebugInfoInternal();
+    std::pair<WifiStatus, std::vector<uint8_t>> requestDriverDebugDumpInternal();
+    std::pair<WifiStatus, std::vector<uint8_t>> requestFirmwareDebugDumpInternal();
+    sp<WifiApIface> newWifiApIface(std::string& ifname);
+    WifiStatus createVirtualApInterface(const std::string& apVirtIf);
+    std::pair<WifiStatus, sp<V1_5::IWifiApIface>> createApIfaceInternal();
+    std::pair<WifiStatus, sp<V1_5::IWifiApIface>> createBridgedApIfaceInternal();
+    std::pair<WifiStatus, std::vector<hidl_string>> getApIfaceNamesInternal();
+    std::pair<WifiStatus, sp<V1_5::IWifiApIface>> getApIfaceInternal(const std::string& ifname);
+    WifiStatus removeApIfaceInternal(const std::string& ifname);
+    WifiStatus removeIfaceInstanceFromBridgedApIfaceInternal(const std::string& brIfaceName,
+                                                             const std::string& ifInstanceName);
+    std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> createNanIfaceInternal();
+    std::pair<WifiStatus, std::vector<hidl_string>> getNanIfaceNamesInternal();
+    std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> getNanIfaceInternal(const std::string& ifname);
+    WifiStatus removeNanIfaceInternal(const std::string& ifname);
+    std::pair<WifiStatus, sp<IWifiP2pIface>> createP2pIfaceInternal();
+    std::pair<WifiStatus, std::vector<hidl_string>> getP2pIfaceNamesInternal();
+    std::pair<WifiStatus, sp<IWifiP2pIface>> getP2pIfaceInternal(const std::string& ifname);
+    WifiStatus removeP2pIfaceInternal(const std::string& ifname);
+    std::pair<WifiStatus, sp<V1_5::IWifiStaIface>> createStaIfaceInternal();
+    std::pair<WifiStatus, std::vector<hidl_string>> getStaIfaceNamesInternal();
+    std::pair<WifiStatus, sp<V1_5::IWifiStaIface>> getStaIfaceInternal(const std::string& ifname);
+    WifiStatus removeStaIfaceInternal(const std::string& ifname);
+    std::pair<WifiStatus, sp<V1_0::IWifiRttController>> createRttControllerInternal(
+            const sp<IWifiIface>& bound_iface);
+    std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
+    getDebugRingBuffersStatusInternal();
+    WifiStatus startLoggingToDebugRingBufferInternal(const hidl_string& ring_name,
+                                                     WifiDebugRingBufferVerboseLevel verbose_level,
+                                                     uint32_t max_interval_in_sec,
+                                                     uint32_t min_data_size_in_bytes);
+    WifiStatus forceDumpToDebugRingBufferInternal(const hidl_string& ring_name);
+    WifiStatus flushRingBufferToFileInternal();
+    WifiStatus stopLoggingToDebugRingBufferInternal();
+    std::pair<WifiStatus, WifiDebugHostWakeReasonStats> getDebugHostWakeReasonStatsInternal();
+    WifiStatus enableDebugErrorAlertsInternal(bool enable);
+    WifiStatus selectTxPowerScenarioInternal(V1_1::IWifiChip::TxPowerScenario scenario);
+    WifiStatus resetTxPowerScenarioInternal();
+    WifiStatus setLatencyModeInternal(LatencyMode mode);
+    WifiStatus registerEventCallbackInternal_1_2(
+            const sp<V1_2::IWifiChipEventCallback>& event_callback);
+    WifiStatus selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario);
+    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_3();
+    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_5();
+    std::pair<WifiStatus, sp<V1_4::IWifiRttController>> createRttControllerInternal_1_4(
+            const sp<IWifiIface>& bound_iface);
+    WifiStatus registerEventCallbackInternal_1_4(
+            const sp<V1_4::IWifiChipEventCallback>& event_callback);
+    WifiStatus setMultiStaPrimaryConnectionInternal(const std::string& ifname);
+    WifiStatus setMultiStaUseCaseInternal(MultiStaUseCase use_case);
+    WifiStatus setCoexUnsafeChannelsInternal(std::vector<CoexUnsafeChannel> unsafe_channels,
+                                             uint32_t restrictions);
+    WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code);
+    std::pair<WifiStatus, std::vector<WifiUsableChannel>> getUsableChannelsInternal(
+            WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask);
+    WifiStatus handleChipConfiguration(std::unique_lock<std::recursive_mutex>* lock,
+                                       ChipModeId mode_id);
+    WifiStatus registerDebugRingBufferCallback();
+    WifiStatus registerRadioModeChangeCallback();
+
+    std::vector<V1_4::IWifiChip::ChipIfaceCombination> getCurrentModeIfaceCombinations();
+    std::map<IfaceType, size_t> getCurrentIfaceCombination();
+    std::vector<std::map<IfaceType, size_t>> expandIfaceCombinations(
+            const V1_4::IWifiChip::ChipIfaceCombination& combination);
+    bool canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(
+            const std::map<IfaceType, size_t>& expanded_combo, IfaceType requested_type);
+    bool canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType requested_type);
+    bool canExpandedIfaceComboSupportIfaceCombo(const std::map<IfaceType, size_t>& expanded_combo,
+                                                const std::map<IfaceType, size_t>& req_combo);
+    bool canCurrentModeSupportIfaceCombo(const std::map<IfaceType, size_t>& req_combo);
+    bool canCurrentModeSupportIfaceOfType(IfaceType requested_type);
+    bool isValidModeId(ChipModeId mode_id);
+    bool isStaApConcurrencyAllowedInCurrentMode();
+    bool isDualStaConcurrencyAllowedInCurrentMode();
+    uint32_t startIdxOfApIface();
+    std::string getFirstActiveWlanIfaceName();
+    std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx);
+    std::string allocateApIfaceName();
+    std::vector<std::string> allocateBridgedApInstanceNames();
+    std::string allocateStaIfaceName();
+    bool writeRingbufferFilesInternal();
+    std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx);
+    void invalidateAndClearBridgedApAll();
+    void invalidateAndClearBridgedAp(const std::string& br_name);
+    bool findUsingNameFromBridgedApInstances(const std::string& name);
+    WifiStatus triggerSubsystemRestartInternal();
+
+    ChipId chip_id_;
+    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    std::weak_ptr<mode_controller::WifiModeController> mode_controller_;
+    std::shared_ptr<iface_util::WifiIfaceUtil> iface_util_;
+    std::vector<sp<WifiApIface>> ap_ifaces_;
+    std::vector<sp<WifiNanIface>> nan_ifaces_;
+    std::vector<sp<WifiP2pIface>> p2p_ifaces_;
+    std::vector<sp<WifiStaIface>> sta_ifaces_;
+    std::vector<sp<WifiRttController>> rtt_controllers_;
+    std::map<std::string, Ringbuffer> ringbuffer_map_;
+    bool is_valid_;
+    // Members pertaining to chip configuration.
+    uint32_t current_mode_id_;
+    std::mutex lock_t;
+    std::vector<V1_4::IWifiChip::ChipMode> modes_;
+    // The legacy ring buffer callback API has only a global callback
+    // registration mechanism. Use this to check if we have already
+    // registered a callback.
+    bool debug_ring_buffer_cb_registered_;
+    hidl_callback_util::HidlCallbackHandler<V1_4::IWifiChipEventCallback> event_cb_handler_;
+
+    const std::function<void(const std::string&)> subsystemCallbackHandler_;
+    std::map<std::string, std::vector<std::string>> br_ifaces_ap_instances_;
+    DISALLOW_COPY_AND_ASSIGN(WifiChip);
+};
+
+}  // namespace implementation
+}  // namespace V1_6
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_CHIP_H_
diff --git a/wifi/1.5/default/wifi_feature_flags.cpp b/wifi/1.6/default/wifi_feature_flags.cpp
similarity index 87%
rename from wifi/1.5/default/wifi_feature_flags.cpp
rename to wifi/1.6/default/wifi_feature_flags.cpp
index 70ce55a..71319e1 100644
--- a/wifi/1.5/default/wifi_feature_flags.cpp
+++ b/wifi/1.6/default/wifi_feature_flags.cpp
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace feature_flags {
 
@@ -117,18 +117,16 @@
  * The main point here is to simplify the syntax required by
  * WIFI_HAL_INTERFACE_COMBINATIONS.
  */
-struct ChipIfaceCombination
-    : public hidl_vec<IWifiChip::ChipIfaceCombinationLimit> {
-    ChipIfaceCombination(
-        const std::initializer_list<IWifiChip::ChipIfaceCombinationLimit> list)
+struct ChipIfaceCombination : public hidl_vec<IWifiChip::ChipIfaceCombinationLimit> {
+    ChipIfaceCombination(const std::initializer_list<IWifiChip::ChipIfaceCombinationLimit> list)
         : hidl_vec(list) {}
 
     operator IWifiChip::ChipIfaceCombination() const { return {*this}; }
 
     static hidl_vec<IWifiChip::ChipIfaceCombination> make_vec(
-        const std::initializer_list<ChipIfaceCombination> list) {
+            const std::initializer_list<ChipIfaceCombination> list) {
         return hidl_vec<IWifiChip::ChipIfaceCombination>(  //
-            std::begin(list), std::end(list));
+                std::begin(list), std::end(list));
     }
 };
 
@@ -137,23 +135,22 @@
 #define P2P IfaceType::P2P
 #define NAN IfaceType::NAN
 static const std::vector<IWifiChip::ChipMode> kChipModesPrimary{
-    {kMainModeId,
-     ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS})},
+        {kMainModeId, ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS})},
 #ifdef WIFI_HAL_INTERFACE_COMBINATIONS_AP
-    {chip_mode_ids::kV1Ap,
-     ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_AP})},
+        {chip_mode_ids::kV1Ap,
+         ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_AP})},
 #endif
 };
 
 static const std::vector<IWifiChip::ChipMode> kChipModesSecondary{
 #ifdef WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP
-    {chip_mode_ids::kV3, ChipIfaceCombination::make_vec(
-                             {WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP})},
+        {chip_mode_ids::kV3,
+         ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP})},
 #endif
 };
 
 constexpr char kDebugPresetInterfaceCombinationIdxProperty[] =
-    "persist.vendor.debug.wifi.hal.preset_interface_combination_idx";
+        "persist.vendor.debug.wifi.hal.preset_interface_combination_idx";
 // List of pre-defined interface combinations that can be enabled at runtime via
 // setting the property: "kDebugPresetInterfaceCombinationIdxProperty" to the
 // corresponding index value.
@@ -200,19 +197,18 @@
 #undef NAN
 
 #ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
-#pragma message                                                               \
-    "WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION is deprecated; override " \
-    "'config_wifi_ap_randomization_supported' in "                            \
-    "frameworks/base/core/res/res/values/config.xml in the device overlay "   \
-    "instead"
+#pragma message                                                                   \
+        "WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION is deprecated; override " \
+        "'config_wifi_ap_randomization_supported' in "                            \
+        "frameworks/base/core/res/res/values/config.xml in the device overlay "   \
+        "instead"
 #endif  // WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
 
 WifiFeatureFlags::WifiFeatureFlags() {}
 
 std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModesForPrimary() {
     std::array<char, PROPERTY_VALUE_MAX> buffer;
-    auto res = property_get(kDebugPresetInterfaceCombinationIdxProperty,
-                            buffer.data(), nullptr);
+    auto res = property_get(kDebugPresetInterfaceCombinationIdxProperty, buffer.data(), nullptr);
     // Debug propety not set, use the device preset interface combination.
     if (res <= 0) return kChipModesPrimary;
 
@@ -226,19 +222,18 @@
     std::string name;
     std::vector<IWifiChip::ChipMode> chip_modes;
     std::tie(name, chip_modes) = kDebugChipModes[idx];
-    LOG(INFO) << "Using debug chip mode: <" << name << "> set via property: "
-              << kDebugPresetInterfaceCombinationIdxProperty;
+    LOG(INFO) << "Using debug chip mode: <" << name
+              << "> set via property: " << kDebugPresetInterfaceCombinationIdxProperty;
     return chip_modes;
 }
 
-std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModes(
-    bool is_primary) {
+std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModes(bool is_primary) {
     return (is_primary) ? getChipModesForPrimary() : kChipModesSecondary;
 }
 
 }  // namespace feature_flags
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_feature_flags.h b/wifi/1.6/default/wifi_feature_flags.h
similarity index 94%
rename from wifi/1.5/default/wifi_feature_flags.h
rename to wifi/1.6/default/wifi_feature_flags.h
index 7d561fc..d5844d9 100644
--- a/wifi/1.5/default/wifi_feature_flags.h
+++ b/wifi/1.6/default/wifi_feature_flags.h
@@ -22,7 +22,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace feature_flags {
 
@@ -38,20 +38,19 @@
 }  // namespace chip_mode_ids
 
 class WifiFeatureFlags {
-   public:
+  public:
     WifiFeatureFlags();
     virtual ~WifiFeatureFlags() = default;
 
-    virtual std::vector<V1_0::IWifiChip::ChipMode> getChipModes(
-        bool is_primary);
+    virtual std::vector<V1_0::IWifiChip::ChipMode> getChipModes(bool is_primary);
 
-   private:
+  private:
     std::vector<V1_0::IWifiChip::ChipMode> getChipModesForPrimary();
 };
 
 }  // namespace feature_flags
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_iface_util.cpp b/wifi/1.6/default/wifi_iface_util.cpp
similarity index 85%
rename from wifi/1.5/default/wifi_iface_util.cpp
rename to wifi/1.6/default/wifi_iface_util.cpp
index 0977026..d55e4f8 100644
--- a/wifi/1.5/default/wifi_iface_util.cpp
+++ b/wifi/1.6/default/wifi_iface_util.cpp
@@ -36,20 +36,18 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace iface_util {
 
-WifiIfaceUtil::WifiIfaceUtil(
-    const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+WifiIfaceUtil::WifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
+                             const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
     : iface_tool_(iface_tool),
       legacy_hal_(legacy_hal),
       random_mac_address_(nullptr),
       event_handlers_map_() {}
 
-std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress(
-    const std::string& iface_name) {
+std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress(const std::string& iface_name) {
     return iface_tool_.lock()->GetFactoryMacAddress(iface_name.c_str());
 }
 
@@ -59,7 +57,7 @@
     legacy_hal::wifi_error legacy_status;
     uint64_t legacy_feature_set;
     std::tie(legacy_status, legacy_feature_set) =
-        legacy_hal_.lock()->getSupportedFeatureSet(iface_name);
+            legacy_hal_.lock()->getSupportedFeatureSet(iface_name);
 
     if (!(legacy_feature_set & WIFI_FEATURE_DYNAMIC_SET_MAC) &&
         !iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) {
@@ -73,8 +71,7 @@
         !iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) {
         LOG(ERROR) << "SetUpState(true) failed. Wait for driver ready.";
         // Wait for driver ready and try to set iface UP again
-        if (legacy_hal_.lock()->waitForDriverReady() !=
-            legacy_hal::WIFI_SUCCESS) {
+        if (legacy_hal_.lock()->waitForDriverReady() != legacy_hal::WIFI_SUCCESS) {
             LOG(ERROR) << "SetUpState(true) wait for driver ready failed.";
             return false;
         }
@@ -104,8 +101,7 @@
     if (random_mac_address_) {
         return *random_mac_address_.get();
     }
-    random_mac_address_ =
-        std::make_unique<std::array<uint8_t, 6>>(createRandomMacAddress());
+    random_mac_address_ = std::make_unique<std::array<uint8_t, 6>>(createRandomMacAddress());
     return *random_mac_address_.get();
 }
 
@@ -114,8 +110,7 @@
     event_handlers_map_[iface_name] = handlers;
 }
 
-void WifiIfaceUtil::unregisterIfaceEventHandlers(
-    const std::string& iface_name) {
+void WifiIfaceUtil::unregisterIfaceEventHandlers(const std::string& iface_name) {
     event_handlers_map_.erase(iface_name);
 }
 
@@ -123,9 +118,8 @@
     std::array<uint8_t, 6> address = {};
     std::random_device rd;
     std::default_random_engine engine(rd());
-    std::uniform_int_distribution<uint8_t> dist(
-        std::numeric_limits<uint8_t>::min(),
-        std::numeric_limits<uint8_t>::max());
+    std::uniform_int_distribution<uint8_t> dist(std::numeric_limits<uint8_t>::min(),
+                                                std::numeric_limits<uint8_t>::max());
     for (size_t i = 0; i < address.size(); i++) {
         address[i] = dist(engine);
     }
@@ -166,19 +160,17 @@
     return iface_tool_.lock()->deleteBridge(br_name);
 }
 
-bool WifiIfaceUtil::addIfaceToBridge(const std::string& br_name,
-                                     const std::string& if_name) {
+bool WifiIfaceUtil::addIfaceToBridge(const std::string& br_name, const std::string& if_name) {
     return iface_tool_.lock()->addIfaceToBridge(br_name, if_name);
 }
 
-bool WifiIfaceUtil::removeIfaceFromBridge(const std::string& br_name,
-                                          const std::string& if_name) {
+bool WifiIfaceUtil::removeIfaceFromBridge(const std::string& br_name, const std::string& if_name) {
     return iface_tool_.lock()->removeIfaceFromBridge(br_name, if_name);
 }
 
 }  // namespace iface_util
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_iface_util.h b/wifi/1.6/default/wifi_iface_util.h
similarity index 85%
rename from wifi/1.5/default/wifi_iface_util.h
rename to wifi/1.6/default/wifi_iface_util.h
index 544f575..c5db5de 100644
--- a/wifi/1.5/default/wifi_iface_util.h
+++ b/wifi/1.6/default/wifi_iface_util.h
@@ -26,7 +26,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace iface_util {
 
@@ -41,15 +41,13 @@
  * Util class for common iface operations.
  */
 class WifiIfaceUtil {
-   public:
+  public:
     WifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
                   const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
     virtual ~WifiIfaceUtil() = default;
 
-    virtual std::array<uint8_t, 6> getFactoryMacAddress(
-        const std::string& iface_name);
-    virtual bool setMacAddress(const std::string& iface_name,
-                               const std::array<uint8_t, 6>& mac);
+    virtual std::array<uint8_t, 6> getFactoryMacAddress(const std::string& iface_name);
+    virtual bool setMacAddress(const std::string& iface_name, const std::array<uint8_t, 6>& mac);
     // Get or create a random MAC address. The MAC address returned from
     // this method will remain the same throughout the lifetime of the HAL
     // daemon. (So, changes on every reboot)
@@ -66,15 +64,13 @@
 
     virtual bool deleteBridge(const std::string& br_name);
 
-    virtual bool addIfaceToBridge(const std::string& br_name,
-                                  const std::string& if_name);
+    virtual bool addIfaceToBridge(const std::string& br_name, const std::string& if_name);
 
-    virtual bool removeIfaceFromBridge(const std::string& br_name,
-                                       const std::string& if_name);
+    virtual bool removeIfaceFromBridge(const std::string& br_name, const std::string& if_name);
     // Get a random MAC address.
     virtual std::array<uint8_t, 6> createRandomMacAddress();
 
-   private:
+  private:
     std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
     std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_;
@@ -83,7 +79,7 @@
 
 }  // namespace iface_util
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.6/default/wifi_legacy_hal.cpp b/wifi/1.6/default/wifi_legacy_hal.cpp
new file mode 100644
index 0000000..e6e8141
--- /dev/null
+++ b/wifi/1.6/default/wifi_legacy_hal.cpp
@@ -0,0 +1,1578 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <array>
+#include <chrono>
+
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+#include <net/if.h>
+
+#include "hidl_sync_util.h"
+#include "wifi_legacy_hal.h"
+#include "wifi_legacy_hal_stubs.h"
+
+namespace {
+// Constants ported over from the legacy HAL calling code
+// (com_android_server_wifi_WifiNative.cpp). This will all be thrown
+// away when this shim layer is replaced by the real vendor
+// implementation.
+static constexpr uint32_t kMaxVersionStringLength = 256;
+static constexpr uint32_t kMaxCachedGscanResults = 64;
+static constexpr uint32_t kMaxGscanFrequenciesForBand = 64;
+static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
+static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
+static constexpr uint32_t kMaxRingBuffers = 10;
+static constexpr uint32_t kMaxWifiUsableChannels = 256;
+// need a long timeout (1000ms) for chips that unload their driver.
+static constexpr uint32_t kMaxStopCompleteWaitMs = 1000;
+static constexpr char kDriverPropName[] = "wlan.driver.status";
+
+// Helper function to create a non-const char* for legacy Hal API's.
+std::vector<char> makeCharVec(const std::string& str) {
+    std::vector<char> vec(str.size() + 1);
+    vec.assign(str.begin(), str.end());
+    vec.push_back('\0');
+    return vec;
+}
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_6 {
+namespace implementation {
+namespace legacy_hal {
+
+// Legacy HAL functions accept "C" style function pointers, so use global
+// functions to pass to the legacy HAL function and store the corresponding
+// std::function methods to be invoked.
+//
+// Callback to be invoked once |stop| is complete
+std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
+void onAsyncStopComplete(wifi_handle handle) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_stop_complete_internal_callback) {
+        on_stop_complete_internal_callback(handle);
+        // Invalidate this callback since we don't want this firing again.
+        on_stop_complete_internal_callback = nullptr;
+    }
+}
+
+// Callback to be invoked for driver dump.
+std::function<void(char*, int)> on_driver_memory_dump_internal_callback;
+void onSyncDriverMemoryDump(char* buffer, int buffer_size) {
+    if (on_driver_memory_dump_internal_callback) {
+        on_driver_memory_dump_internal_callback(buffer, buffer_size);
+    }
+}
+
+// Callback to be invoked for firmware dump.
+std::function<void(char*, int)> on_firmware_memory_dump_internal_callback;
+void onSyncFirmwareMemoryDump(char* buffer, int buffer_size) {
+    if (on_firmware_memory_dump_internal_callback) {
+        on_firmware_memory_dump_internal_callback(buffer, buffer_size);
+    }
+}
+
+// Callback to be invoked for Gscan events.
+std::function<void(wifi_request_id, wifi_scan_event)> on_gscan_event_internal_callback;
+void onAsyncGscanEvent(wifi_request_id id, wifi_scan_event event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_gscan_event_internal_callback) {
+        on_gscan_event_internal_callback(id, event);
+    }
+}
+
+// Callback to be invoked for Gscan full results.
+std::function<void(wifi_request_id, wifi_scan_result*, uint32_t)>
+        on_gscan_full_result_internal_callback;
+void onAsyncGscanFullResult(wifi_request_id id, wifi_scan_result* result,
+                            uint32_t buckets_scanned) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_gscan_full_result_internal_callback) {
+        on_gscan_full_result_internal_callback(id, result, buckets_scanned);
+    }
+}
+
+// Callback to be invoked for link layer stats results.
+std::function<void((wifi_request_id, wifi_iface_stat*, int, wifi_radio_stat*))>
+        on_link_layer_stats_result_internal_callback;
+void onSyncLinkLayerStatsResult(wifi_request_id id, wifi_iface_stat* iface_stat, int num_radios,
+                                wifi_radio_stat* radio_stat) {
+    if (on_link_layer_stats_result_internal_callback) {
+        on_link_layer_stats_result_internal_callback(id, iface_stat, num_radios, radio_stat);
+    }
+}
+
+// Callback to be invoked for rssi threshold breach.
+std::function<void((wifi_request_id, uint8_t*, int8_t))>
+        on_rssi_threshold_breached_internal_callback;
+void onAsyncRssiThresholdBreached(wifi_request_id id, uint8_t* bssid, int8_t rssi) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_rssi_threshold_breached_internal_callback) {
+        on_rssi_threshold_breached_internal_callback(id, bssid, rssi);
+    }
+}
+
+// Callback to be invoked for ring buffer data indication.
+std::function<void(char*, char*, int, wifi_ring_buffer_status*)>
+        on_ring_buffer_data_internal_callback;
+void onAsyncRingBufferData(char* ring_name, char* buffer, int buffer_size,
+                           wifi_ring_buffer_status* status) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_ring_buffer_data_internal_callback) {
+        on_ring_buffer_data_internal_callback(ring_name, buffer, buffer_size, status);
+    }
+}
+
+// Callback to be invoked for error alert indication.
+std::function<void(wifi_request_id, char*, int, int)> on_error_alert_internal_callback;
+void onAsyncErrorAlert(wifi_request_id id, char* buffer, int buffer_size, int err_code) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_error_alert_internal_callback) {
+        on_error_alert_internal_callback(id, buffer, buffer_size, err_code);
+    }
+}
+
+// Callback to be invoked for radio mode change indication.
+std::function<void(wifi_request_id, uint32_t, wifi_mac_info*)>
+        on_radio_mode_change_internal_callback;
+void onAsyncRadioModeChange(wifi_request_id id, uint32_t num_macs, wifi_mac_info* mac_infos) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_radio_mode_change_internal_callback) {
+        on_radio_mode_change_internal_callback(id, num_macs, mac_infos);
+    }
+}
+
+// Callback to be invoked to report subsystem restart
+std::function<void(const char*)> on_subsystem_restart_internal_callback;
+void onAsyncSubsystemRestart(const char* error) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_subsystem_restart_internal_callback) {
+        on_subsystem_restart_internal_callback(error);
+    }
+}
+
+// Callback to be invoked for rtt results results.
+std::function<void(wifi_request_id, unsigned num_results, wifi_rtt_result* rtt_results[])>
+        on_rtt_results_internal_callback;
+void onAsyncRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* rtt_results[]) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_rtt_results_internal_callback) {
+        on_rtt_results_internal_callback(id, num_results, rtt_results);
+        on_rtt_results_internal_callback = nullptr;
+    }
+}
+
+// Callbacks for the various NAN operations.
+// NOTE: These have very little conversions to perform before invoking the user
+// callbacks.
+// So, handle all of them here directly to avoid adding an unnecessary layer.
+std::function<void(transaction_id, const NanResponseMsg&)> on_nan_notify_response_user_callback;
+void onAysncNanNotifyResponse(transaction_id id, NanResponseMsg* msg) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_notify_response_user_callback && msg) {
+        on_nan_notify_response_user_callback(id, *msg);
+    }
+}
+
+std::function<void(const NanPublishRepliedInd&)> on_nan_event_publish_replied_user_callback;
+void onAysncNanEventPublishReplied(NanPublishRepliedInd* /* event */) {
+    LOG(ERROR) << "onAysncNanEventPublishReplied triggered";
+}
+
+std::function<void(const NanPublishTerminatedInd&)> on_nan_event_publish_terminated_user_callback;
+void onAysncNanEventPublishTerminated(NanPublishTerminatedInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_publish_terminated_user_callback && event) {
+        on_nan_event_publish_terminated_user_callback(*event);
+    }
+}
+
+std::function<void(const NanMatchInd&)> on_nan_event_match_user_callback;
+void onAysncNanEventMatch(NanMatchInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_match_user_callback && event) {
+        on_nan_event_match_user_callback(*event);
+    }
+}
+
+std::function<void(const NanMatchExpiredInd&)> on_nan_event_match_expired_user_callback;
+void onAysncNanEventMatchExpired(NanMatchExpiredInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_match_expired_user_callback && event) {
+        on_nan_event_match_expired_user_callback(*event);
+    }
+}
+
+std::function<void(const NanSubscribeTerminatedInd&)>
+        on_nan_event_subscribe_terminated_user_callback;
+void onAysncNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_subscribe_terminated_user_callback && event) {
+        on_nan_event_subscribe_terminated_user_callback(*event);
+    }
+}
+
+std::function<void(const NanFollowupInd&)> on_nan_event_followup_user_callback;
+void onAysncNanEventFollowup(NanFollowupInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_followup_user_callback && event) {
+        on_nan_event_followup_user_callback(*event);
+    }
+}
+
+std::function<void(const NanDiscEngEventInd&)> on_nan_event_disc_eng_event_user_callback;
+void onAysncNanEventDiscEngEvent(NanDiscEngEventInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_disc_eng_event_user_callback && event) {
+        on_nan_event_disc_eng_event_user_callback(*event);
+    }
+}
+
+std::function<void(const NanDisabledInd&)> on_nan_event_disabled_user_callback;
+void onAysncNanEventDisabled(NanDisabledInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_disabled_user_callback && event) {
+        on_nan_event_disabled_user_callback(*event);
+    }
+}
+
+std::function<void(const NanTCAInd&)> on_nan_event_tca_user_callback;
+void onAysncNanEventTca(NanTCAInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_tca_user_callback && event) {
+        on_nan_event_tca_user_callback(*event);
+    }
+}
+
+std::function<void(const NanBeaconSdfPayloadInd&)> on_nan_event_beacon_sdf_payload_user_callback;
+void onAysncNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_beacon_sdf_payload_user_callback && event) {
+        on_nan_event_beacon_sdf_payload_user_callback(*event);
+    }
+}
+
+std::function<void(const NanDataPathRequestInd&)> on_nan_event_data_path_request_user_callback;
+void onAysncNanEventDataPathRequest(NanDataPathRequestInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_data_path_request_user_callback && event) {
+        on_nan_event_data_path_request_user_callback(*event);
+    }
+}
+std::function<void(const NanDataPathConfirmInd&)> on_nan_event_data_path_confirm_user_callback;
+void onAysncNanEventDataPathConfirm(NanDataPathConfirmInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_data_path_confirm_user_callback && event) {
+        on_nan_event_data_path_confirm_user_callback(*event);
+    }
+}
+
+std::function<void(const NanDataPathEndInd&)> on_nan_event_data_path_end_user_callback;
+void onAysncNanEventDataPathEnd(NanDataPathEndInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_data_path_end_user_callback && event) {
+        on_nan_event_data_path_end_user_callback(*event);
+    }
+}
+
+std::function<void(const NanTransmitFollowupInd&)> on_nan_event_transmit_follow_up_user_callback;
+void onAysncNanEventTransmitFollowUp(NanTransmitFollowupInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_transmit_follow_up_user_callback && event) {
+        on_nan_event_transmit_follow_up_user_callback(*event);
+    }
+}
+
+std::function<void(const NanRangeRequestInd&)> on_nan_event_range_request_user_callback;
+void onAysncNanEventRangeRequest(NanRangeRequestInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_range_request_user_callback && event) {
+        on_nan_event_range_request_user_callback(*event);
+    }
+}
+
+std::function<void(const NanRangeReportInd&)> on_nan_event_range_report_user_callback;
+void onAysncNanEventRangeReport(NanRangeReportInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_range_report_user_callback && event) {
+        on_nan_event_range_report_user_callback(*event);
+    }
+}
+
+std::function<void(const NanDataPathScheduleUpdateInd&)> on_nan_event_schedule_update_user_callback;
+void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_schedule_update_user_callback && event) {
+        on_nan_event_schedule_update_user_callback(*event);
+    }
+}
+
+// Callbacks for the various TWT operations.
+std::function<void(const TwtSetupResponse&)> on_twt_event_setup_response_callback;
+void onAsyncTwtEventSetupResponse(TwtSetupResponse* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_twt_event_setup_response_callback && event) {
+        on_twt_event_setup_response_callback(*event);
+    }
+}
+
+std::function<void(const TwtTeardownCompletion&)> on_twt_event_teardown_completion_callback;
+void onAsyncTwtEventTeardownCompletion(TwtTeardownCompletion* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_twt_event_teardown_completion_callback && event) {
+        on_twt_event_teardown_completion_callback(*event);
+    }
+}
+
+std::function<void(const TwtInfoFrameReceived&)> on_twt_event_info_frame_received_callback;
+void onAsyncTwtEventInfoFrameReceived(TwtInfoFrameReceived* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_twt_event_info_frame_received_callback && event) {
+        on_twt_event_info_frame_received_callback(*event);
+    }
+}
+
+std::function<void(const TwtDeviceNotify&)> on_twt_event_device_notify_callback;
+void onAsyncTwtEventDeviceNotify(TwtDeviceNotify* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_twt_event_device_notify_callback && event) {
+        on_twt_event_device_notify_callback(*event);
+    }
+}
+
+// End of the free-standing "C" style callbacks.
+
+WifiLegacyHal::WifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
+                             const wifi_hal_fn& fn, bool is_primary)
+    : global_func_table_(fn),
+      global_handle_(nullptr),
+      awaiting_event_loop_termination_(false),
+      is_started_(false),
+      iface_tool_(iface_tool),
+      is_primary_(is_primary) {}
+
+wifi_error WifiLegacyHal::initialize() {
+    LOG(DEBUG) << "Initialize legacy HAL";
+    // this now does nothing, since HAL function table is provided
+    // to the constructor
+    return WIFI_SUCCESS;
+}
+
+wifi_error WifiLegacyHal::start() {
+    // Ensure that we're starting in a good state.
+    CHECK(global_func_table_.wifi_initialize && !global_handle_ && iface_name_to_handle_.empty() &&
+          !awaiting_event_loop_termination_);
+    if (is_started_) {
+        LOG(DEBUG) << "Legacy HAL already started";
+        return WIFI_SUCCESS;
+    }
+    LOG(DEBUG) << "Waiting for the driver ready";
+    wifi_error status = global_func_table_.wifi_wait_for_driver_ready();
+    if (status == WIFI_ERROR_TIMED_OUT || status == WIFI_ERROR_UNKNOWN) {
+        LOG(ERROR) << "Failed or timed out awaiting driver ready";
+        return status;
+    }
+
+    if (is_primary_) {
+        property_set(kDriverPropName, "ok");
+
+        if (!iface_tool_.lock()->SetWifiUpState(true)) {
+            LOG(ERROR) << "Failed to set WiFi interface up";
+            return WIFI_ERROR_UNKNOWN;
+        }
+    }
+
+    LOG(DEBUG) << "Starting legacy HAL";
+    status = global_func_table_.wifi_initialize(&global_handle_);
+    if (status != WIFI_SUCCESS || !global_handle_) {
+        LOG(ERROR) << "Failed to retrieve global handle";
+        return status;
+    }
+    std::thread(&WifiLegacyHal::runEventLoop, this).detach();
+    status = retrieveIfaceHandles();
+    if (status != WIFI_SUCCESS || iface_name_to_handle_.empty()) {
+        LOG(ERROR) << "Failed to retrieve wlan interface handle";
+        return status;
+    }
+    LOG(DEBUG) << "Legacy HAL start complete";
+    is_started_ = true;
+    return WIFI_SUCCESS;
+}
+
+wifi_error WifiLegacyHal::stop(
+        /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
+        const std::function<void()>& on_stop_complete_user_callback) {
+    if (!is_started_) {
+        LOG(DEBUG) << "Legacy HAL already stopped";
+        on_stop_complete_user_callback();
+        return WIFI_SUCCESS;
+    }
+    LOG(DEBUG) << "Stopping legacy HAL";
+    on_stop_complete_internal_callback = [on_stop_complete_user_callback,
+                                          this](wifi_handle handle) {
+        CHECK_EQ(global_handle_, handle) << "Handle mismatch";
+        LOG(INFO) << "Legacy HAL stop complete callback received";
+        // Invalidate all the internal pointers now that the HAL is
+        // stopped.
+        invalidate();
+        if (is_primary_) iface_tool_.lock()->SetWifiUpState(false);
+        on_stop_complete_user_callback();
+        is_started_ = false;
+    };
+    awaiting_event_loop_termination_ = true;
+    global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete);
+    const auto status =
+            stop_wait_cv_.wait_for(*lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs),
+                                   [this] { return !awaiting_event_loop_termination_; });
+    if (!status) {
+        LOG(ERROR) << "Legacy HAL stop failed or timed out";
+        return WIFI_ERROR_UNKNOWN;
+    }
+    LOG(DEBUG) << "Legacy HAL stop complete";
+    return WIFI_SUCCESS;
+}
+
+bool WifiLegacyHal::isStarted() {
+    return is_started_;
+}
+
+wifi_error WifiLegacyHal::waitForDriverReady() {
+    return global_func_table_.wifi_wait_for_driver_ready();
+}
+
+std::pair<wifi_error, std::string> WifiLegacyHal::getDriverVersion(const std::string& iface_name) {
+    std::array<char, kMaxVersionStringLength> buffer;
+    buffer.fill(0);
+    wifi_error status = global_func_table_.wifi_get_driver_version(getIfaceHandle(iface_name),
+                                                                   buffer.data(), buffer.size());
+    return {status, buffer.data()};
+}
+
+std::pair<wifi_error, std::string> WifiLegacyHal::getFirmwareVersion(
+        const std::string& iface_name) {
+    std::array<char, kMaxVersionStringLength> buffer;
+    buffer.fill(0);
+    wifi_error status = global_func_table_.wifi_get_firmware_version(getIfaceHandle(iface_name),
+                                                                     buffer.data(), buffer.size());
+    return {status, buffer.data()};
+}
+
+std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::requestDriverMemoryDump(
+        const std::string& iface_name) {
+    std::vector<uint8_t> driver_dump;
+    on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer, int buffer_size) {
+        driver_dump.insert(driver_dump.end(), reinterpret_cast<uint8_t*>(buffer),
+                           reinterpret_cast<uint8_t*>(buffer) + buffer_size);
+    };
+    wifi_error status = global_func_table_.wifi_get_driver_memory_dump(getIfaceHandle(iface_name),
+                                                                       {onSyncDriverMemoryDump});
+    on_driver_memory_dump_internal_callback = nullptr;
+    return {status, std::move(driver_dump)};
+}
+
+std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::requestFirmwareMemoryDump(
+        const std::string& iface_name) {
+    std::vector<uint8_t> firmware_dump;
+    on_firmware_memory_dump_internal_callback = [&firmware_dump](char* buffer, int buffer_size) {
+        firmware_dump.insert(firmware_dump.end(), reinterpret_cast<uint8_t*>(buffer),
+                             reinterpret_cast<uint8_t*>(buffer) + buffer_size);
+    };
+    wifi_error status = global_func_table_.wifi_get_firmware_memory_dump(
+            getIfaceHandle(iface_name), {onSyncFirmwareMemoryDump});
+    on_firmware_memory_dump_internal_callback = nullptr;
+    return {status, std::move(firmware_dump)};
+}
+
+std::pair<wifi_error, uint64_t> WifiLegacyHal::getSupportedFeatureSet(
+        const std::string& iface_name) {
+    feature_set set = 0, chip_set = 0;
+    wifi_error status = WIFI_SUCCESS;
+
+    static_assert(sizeof(set) == sizeof(uint64_t),
+                  "Some feature_flags can not be represented in output");
+    wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
+
+    global_func_table_.wifi_get_chip_feature_set(
+            global_handle_, &chip_set); /* ignore error, chip_set will stay 0 */
+
+    if (iface_handle) {
+        status = global_func_table_.wifi_get_supported_feature_set(iface_handle, &set);
+    }
+    return {status, static_cast<uint64_t>(set | chip_set)};
+}
+
+std::pair<wifi_error, PacketFilterCapabilities> WifiLegacyHal::getPacketFilterCapabilities(
+        const std::string& iface_name) {
+    PacketFilterCapabilities caps;
+    wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
+            getIfaceHandle(iface_name), &caps.version, &caps.max_len);
+    return {status, caps};
+}
+
+wifi_error WifiLegacyHal::setPacketFilter(const std::string& iface_name,
+                                          const std::vector<uint8_t>& program) {
+    return global_func_table_.wifi_set_packet_filter(getIfaceHandle(iface_name), program.data(),
+                                                     program.size());
+}
+
+std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::readApfPacketFilterData(
+        const std::string& iface_name) {
+    PacketFilterCapabilities caps;
+    wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
+            getIfaceHandle(iface_name), &caps.version, &caps.max_len);
+    if (status != WIFI_SUCCESS) {
+        return {status, {}};
+    }
+
+    // Size the buffer to read the entire program & work memory.
+    std::vector<uint8_t> buffer(caps.max_len);
+
+    status = global_func_table_.wifi_read_packet_filter(
+            getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(), buffer.size());
+    return {status, move(buffer)};
+}
+
+std::pair<wifi_error, wifi_gscan_capabilities> WifiLegacyHal::getGscanCapabilities(
+        const std::string& iface_name) {
+    wifi_gscan_capabilities caps;
+    wifi_error status =
+            global_func_table_.wifi_get_gscan_capabilities(getIfaceHandle(iface_name), &caps);
+    return {status, caps};
+}
+
+wifi_error WifiLegacyHal::startGscan(
+        const std::string& iface_name, wifi_request_id id, const wifi_scan_cmd_params& params,
+        const std::function<void(wifi_request_id)>& on_failure_user_callback,
+        const on_gscan_results_callback& on_results_user_callback,
+        const on_gscan_full_result_callback& on_full_result_user_callback) {
+    // If there is already an ongoing background scan, reject new scan requests.
+    if (on_gscan_event_internal_callback || on_gscan_full_result_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+
+    // This callback will be used to either trigger |on_results_user_callback|
+    // or |on_failure_user_callback|.
+    on_gscan_event_internal_callback = [iface_name, on_failure_user_callback,
+                                        on_results_user_callback,
+                                        this](wifi_request_id id, wifi_scan_event event) {
+        switch (event) {
+            case WIFI_SCAN_RESULTS_AVAILABLE:
+            case WIFI_SCAN_THRESHOLD_NUM_SCANS:
+            case WIFI_SCAN_THRESHOLD_PERCENT: {
+                wifi_error status;
+                std::vector<wifi_cached_scan_results> cached_scan_results;
+                std::tie(status, cached_scan_results) = getGscanCachedResults(iface_name);
+                if (status == WIFI_SUCCESS) {
+                    on_results_user_callback(id, cached_scan_results);
+                    return;
+                }
+                FALLTHROUGH_INTENDED;
+            }
+            // Fall through if failed. Failure to retrieve cached scan
+            // results should trigger a background scan failure.
+            case WIFI_SCAN_FAILED:
+                on_failure_user_callback(id);
+                on_gscan_event_internal_callback = nullptr;
+                on_gscan_full_result_internal_callback = nullptr;
+                return;
+        }
+        LOG(FATAL) << "Unexpected gscan event received: " << event;
+    };
+
+    on_gscan_full_result_internal_callback = [on_full_result_user_callback](
+                                                     wifi_request_id id, wifi_scan_result* result,
+                                                     uint32_t buckets_scanned) {
+        if (result) {
+            on_full_result_user_callback(id, result, buckets_scanned);
+        }
+    };
+
+    wifi_scan_result_handler handler = {onAsyncGscanFullResult, onAsyncGscanEvent};
+    wifi_error status =
+            global_func_table_.wifi_start_gscan(id, getIfaceHandle(iface_name), params, handler);
+    if (status != WIFI_SUCCESS) {
+        on_gscan_event_internal_callback = nullptr;
+        on_gscan_full_result_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::stopGscan(const std::string& iface_name, wifi_request_id id) {
+    // If there is no an ongoing background scan, reject stop requests.
+    // TODO(b/32337212): This needs to be handled by the HIDL object because we
+    // need to return the NOT_STARTED error code.
+    if (!on_gscan_event_internal_callback && !on_gscan_full_result_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    wifi_error status = global_func_table_.wifi_stop_gscan(id, getIfaceHandle(iface_name));
+    // If the request Id is wrong, don't stop the ongoing background scan. Any
+    // other error should be treated as the end of background scan.
+    if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
+        on_gscan_event_internal_callback = nullptr;
+        on_gscan_full_result_internal_callback = nullptr;
+    }
+    return status;
+}
+
+std::pair<wifi_error, std::vector<uint32_t>> WifiLegacyHal::getValidFrequenciesForBand(
+        const std::string& iface_name, wifi_band band) {
+    static_assert(sizeof(uint32_t) >= sizeof(wifi_channel),
+                  "Wifi Channel cannot be represented in output");
+    std::vector<uint32_t> freqs;
+    freqs.resize(kMaxGscanFrequenciesForBand);
+    int32_t num_freqs = 0;
+    wifi_error status = global_func_table_.wifi_get_valid_channels(
+            getIfaceHandle(iface_name), band, freqs.size(),
+            reinterpret_cast<wifi_channel*>(freqs.data()), &num_freqs);
+    CHECK(num_freqs >= 0 && static_cast<uint32_t>(num_freqs) <= kMaxGscanFrequenciesForBand);
+    freqs.resize(num_freqs);
+    return {status, std::move(freqs)};
+}
+
+wifi_error WifiLegacyHal::setDfsFlag(const std::string& iface_name, bool dfs_on) {
+    return global_func_table_.wifi_set_nodfs_flag(getIfaceHandle(iface_name), dfs_on ? 0 : 1);
+}
+
+wifi_error WifiLegacyHal::enableLinkLayerStats(const std::string& iface_name, bool debug) {
+    wifi_link_layer_params params;
+    params.mpdu_size_threshold = kLinkLayerStatsDataMpduSizeThreshold;
+    params.aggressive_statistics_gathering = debug;
+    return global_func_table_.wifi_set_link_stats(getIfaceHandle(iface_name), params);
+}
+
+wifi_error WifiLegacyHal::disableLinkLayerStats(const std::string& iface_name) {
+    // TODO: Do we care about these responses?
+    uint32_t clear_mask_rsp;
+    uint8_t stop_rsp;
+    return global_func_table_.wifi_clear_link_stats(getIfaceHandle(iface_name), 0xFFFFFFFF,
+                                                    &clear_mask_rsp, 1, &stop_rsp);
+}
+
+std::pair<wifi_error, LinkLayerStats> WifiLegacyHal::getLinkLayerStats(
+        const std::string& iface_name) {
+    LinkLayerStats link_stats{};
+    LinkLayerStats* link_stats_ptr = &link_stats;
+
+    on_link_layer_stats_result_internal_callback = [&link_stats_ptr](
+                                                           wifi_request_id /* id */,
+                                                           wifi_iface_stat* iface_stats_ptr,
+                                                           int num_radios,
+                                                           wifi_radio_stat* radio_stats_ptr) {
+        wifi_radio_stat* l_radio_stats_ptr;
+        wifi_peer_info* l_peer_info_stats_ptr;
+
+        if (iface_stats_ptr != nullptr) {
+            link_stats_ptr->iface = *iface_stats_ptr;
+            l_peer_info_stats_ptr = iface_stats_ptr->peer_info;
+            for (uint32_t i = 0; i < iface_stats_ptr->num_peers; i++) {
+                WifiPeerInfo peer;
+                peer.peer_info = *l_peer_info_stats_ptr;
+                if (l_peer_info_stats_ptr->num_rate > 0) {
+                    /* Copy the rate stats */
+                    peer.rate_stats.assign(
+                            l_peer_info_stats_ptr->rate_stats,
+                            l_peer_info_stats_ptr->rate_stats + l_peer_info_stats_ptr->num_rate);
+                }
+                peer.peer_info.num_rate = 0;
+                link_stats_ptr->peers.push_back(peer);
+                l_peer_info_stats_ptr =
+                        (wifi_peer_info*)((u8*)l_peer_info_stats_ptr + sizeof(wifi_peer_info) +
+                                          (sizeof(wifi_rate_stat) *
+                                           l_peer_info_stats_ptr->num_rate));
+            }
+            link_stats_ptr->iface.num_peers = 0;
+        } else {
+            LOG(ERROR) << "Invalid iface stats in link layer stats";
+        }
+        if (num_radios <= 0 || radio_stats_ptr == nullptr) {
+            LOG(ERROR) << "Invalid radio stats in link layer stats";
+            return;
+        }
+        l_radio_stats_ptr = radio_stats_ptr;
+        for (int i = 0; i < num_radios; i++) {
+            LinkLayerRadioStats radio;
+
+            radio.stats = *l_radio_stats_ptr;
+            // Copy over the tx level array to the separate vector.
+            if (l_radio_stats_ptr->num_tx_levels > 0 &&
+                l_radio_stats_ptr->tx_time_per_levels != nullptr) {
+                radio.tx_time_per_levels.assign(
+                        l_radio_stats_ptr->tx_time_per_levels,
+                        l_radio_stats_ptr->tx_time_per_levels + l_radio_stats_ptr->num_tx_levels);
+            }
+            radio.stats.num_tx_levels = 0;
+            radio.stats.tx_time_per_levels = nullptr;
+            /* Copy over the channel stat to separate vector */
+            if (l_radio_stats_ptr->num_channels > 0) {
+                /* Copy the channel stats */
+                radio.channel_stats.assign(
+                        l_radio_stats_ptr->channels,
+                        l_radio_stats_ptr->channels + l_radio_stats_ptr->num_channels);
+            }
+            link_stats_ptr->radios.push_back(radio);
+            l_radio_stats_ptr =
+                    (wifi_radio_stat*)((u8*)l_radio_stats_ptr + sizeof(wifi_radio_stat) +
+                                       (sizeof(wifi_channel_stat) *
+                                        l_radio_stats_ptr->num_channels));
+        }
+    };
+
+    wifi_error status = global_func_table_.wifi_get_link_stats(0, getIfaceHandle(iface_name),
+                                                               {onSyncLinkLayerStatsResult});
+    on_link_layer_stats_result_internal_callback = nullptr;
+    return {status, link_stats};
+}
+
+wifi_error WifiLegacyHal::startRssiMonitoring(
+        const std::string& iface_name, wifi_request_id id, int8_t max_rssi, int8_t min_rssi,
+        const on_rssi_threshold_breached_callback& on_threshold_breached_user_callback) {
+    if (on_rssi_threshold_breached_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_rssi_threshold_breached_internal_callback = [on_threshold_breached_user_callback](
+                                                           wifi_request_id id, uint8_t* bssid_ptr,
+                                                           int8_t rssi) {
+        if (!bssid_ptr) {
+            return;
+        }
+        std::array<uint8_t, 6> bssid_arr;
+        // |bssid_ptr| pointer is assumed to have 6 bytes for the mac
+        // address.
+        std::copy(bssid_ptr, bssid_ptr + 6, std::begin(bssid_arr));
+        on_threshold_breached_user_callback(id, bssid_arr, rssi);
+    };
+    wifi_error status = global_func_table_.wifi_start_rssi_monitoring(
+            id, getIfaceHandle(iface_name), max_rssi, min_rssi, {onAsyncRssiThresholdBreached});
+    if (status != WIFI_SUCCESS) {
+        on_rssi_threshold_breached_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::stopRssiMonitoring(const std::string& iface_name, wifi_request_id id) {
+    if (!on_rssi_threshold_breached_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    wifi_error status =
+            global_func_table_.wifi_stop_rssi_monitoring(id, getIfaceHandle(iface_name));
+    // If the request Id is wrong, don't stop the ongoing rssi monitoring. Any
+    // other error should be treated as the end of background scan.
+    if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
+        on_rssi_threshold_breached_internal_callback = nullptr;
+    }
+    return status;
+}
+
+std::pair<wifi_error, wifi_roaming_capabilities> WifiLegacyHal::getRoamingCapabilities(
+        const std::string& iface_name) {
+    wifi_roaming_capabilities caps;
+    wifi_error status =
+            global_func_table_.wifi_get_roaming_capabilities(getIfaceHandle(iface_name), &caps);
+    return {status, caps};
+}
+
+wifi_error WifiLegacyHal::configureRoaming(const std::string& iface_name,
+                                           const wifi_roaming_config& config) {
+    wifi_roaming_config config_internal = config;
+    return global_func_table_.wifi_configure_roaming(getIfaceHandle(iface_name), &config_internal);
+}
+
+wifi_error WifiLegacyHal::enableFirmwareRoaming(const std::string& iface_name,
+                                                fw_roaming_state_t state) {
+    return global_func_table_.wifi_enable_firmware_roaming(getIfaceHandle(iface_name), state);
+}
+
+wifi_error WifiLegacyHal::configureNdOffload(const std::string& iface_name, bool enable) {
+    return global_func_table_.wifi_configure_nd_offload(getIfaceHandle(iface_name), enable);
+}
+
+wifi_error WifiLegacyHal::startSendingOffloadedPacket(const std::string& iface_name,
+                                                      uint32_t cmd_id, uint16_t ether_type,
+                                                      const std::vector<uint8_t>& ip_packet_data,
+                                                      const std::array<uint8_t, 6>& src_address,
+                                                      const std::array<uint8_t, 6>& dst_address,
+                                                      uint32_t period_in_ms) {
+    std::vector<uint8_t> ip_packet_data_internal(ip_packet_data);
+    std::vector<uint8_t> src_address_internal(src_address.data(),
+                                              src_address.data() + src_address.size());
+    std::vector<uint8_t> dst_address_internal(dst_address.data(),
+                                              dst_address.data() + dst_address.size());
+    return global_func_table_.wifi_start_sending_offloaded_packet(
+            cmd_id, getIfaceHandle(iface_name), ether_type, ip_packet_data_internal.data(),
+            ip_packet_data_internal.size(), src_address_internal.data(),
+            dst_address_internal.data(), period_in_ms);
+}
+
+wifi_error WifiLegacyHal::stopSendingOffloadedPacket(const std::string& iface_name,
+                                                     uint32_t cmd_id) {
+    return global_func_table_.wifi_stop_sending_offloaded_packet(cmd_id,
+                                                                 getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::selectTxPowerScenario(const std::string& iface_name,
+                                                wifi_power_scenario scenario) {
+    return global_func_table_.wifi_select_tx_power_scenario(getIfaceHandle(iface_name), scenario);
+}
+
+wifi_error WifiLegacyHal::resetTxPowerScenario(const std::string& iface_name) {
+    return global_func_table_.wifi_reset_tx_power_scenario(getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::setLatencyMode(const std::string& iface_name, wifi_latency_mode mode) {
+    return global_func_table_.wifi_set_latency_mode(getIfaceHandle(iface_name), mode);
+}
+
+wifi_error WifiLegacyHal::setThermalMitigationMode(wifi_thermal_mode mode,
+                                                   uint32_t completion_window) {
+    return global_func_table_.wifi_set_thermal_mitigation_mode(global_handle_, mode,
+                                                               completion_window);
+}
+
+wifi_error WifiLegacyHal::setDscpToAccessCategoryMapping(uint32_t start, uint32_t end,
+                                                         uint32_t access_category) {
+    return global_func_table_.wifi_map_dscp_access_category(global_handle_, start, end,
+                                                            access_category);
+}
+
+wifi_error WifiLegacyHal::resetDscpToAccessCategoryMapping() {
+    return global_func_table_.wifi_reset_dscp_mapping(global_handle_);
+}
+
+std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet(
+        const std::string& iface_name) {
+    uint32_t supported_feature_flags = 0;
+    wifi_error status = WIFI_SUCCESS;
+
+    wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
+
+    if (iface_handle) {
+        status = global_func_table_.wifi_get_logger_supported_feature_set(iface_handle,
+                                                                          &supported_feature_flags);
+    }
+    return {status, supported_feature_flags};
+}
+
+wifi_error WifiLegacyHal::startPktFateMonitoring(const std::string& iface_name) {
+    return global_func_table_.wifi_start_pkt_fate_monitoring(getIfaceHandle(iface_name));
+}
+
+std::pair<wifi_error, std::vector<wifi_tx_report>> WifiLegacyHal::getTxPktFates(
+        const std::string& iface_name) {
+    std::vector<wifi_tx_report> tx_pkt_fates;
+    tx_pkt_fates.resize(MAX_FATE_LOG_LEN);
+    size_t num_fates = 0;
+    wifi_error status = global_func_table_.wifi_get_tx_pkt_fates(
+            getIfaceHandle(iface_name), tx_pkt_fates.data(), tx_pkt_fates.size(), &num_fates);
+    CHECK(num_fates <= MAX_FATE_LOG_LEN);
+    tx_pkt_fates.resize(num_fates);
+    return {status, std::move(tx_pkt_fates)};
+}
+
+std::pair<wifi_error, std::vector<wifi_rx_report>> WifiLegacyHal::getRxPktFates(
+        const std::string& iface_name) {
+    std::vector<wifi_rx_report> rx_pkt_fates;
+    rx_pkt_fates.resize(MAX_FATE_LOG_LEN);
+    size_t num_fates = 0;
+    wifi_error status = global_func_table_.wifi_get_rx_pkt_fates(
+            getIfaceHandle(iface_name), rx_pkt_fates.data(), rx_pkt_fates.size(), &num_fates);
+    CHECK(num_fates <= MAX_FATE_LOG_LEN);
+    rx_pkt_fates.resize(num_fates);
+    return {status, std::move(rx_pkt_fates)};
+}
+
+std::pair<wifi_error, WakeReasonStats> WifiLegacyHal::getWakeReasonStats(
+        const std::string& iface_name) {
+    WakeReasonStats stats;
+    stats.cmd_event_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
+    stats.driver_fw_local_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
+
+    // This legacy struct needs separate memory to store the variable sized wake
+    // reason types.
+    stats.wake_reason_cnt.cmd_event_wake_cnt =
+            reinterpret_cast<int32_t*>(stats.cmd_event_wake_cnt.data());
+    stats.wake_reason_cnt.cmd_event_wake_cnt_sz = stats.cmd_event_wake_cnt.size();
+    stats.wake_reason_cnt.cmd_event_wake_cnt_used = 0;
+    stats.wake_reason_cnt.driver_fw_local_wake_cnt =
+            reinterpret_cast<int32_t*>(stats.driver_fw_local_wake_cnt.data());
+    stats.wake_reason_cnt.driver_fw_local_wake_cnt_sz = stats.driver_fw_local_wake_cnt.size();
+    stats.wake_reason_cnt.driver_fw_local_wake_cnt_used = 0;
+
+    wifi_error status = global_func_table_.wifi_get_wake_reason_stats(getIfaceHandle(iface_name),
+                                                                      &stats.wake_reason_cnt);
+
+    CHECK(stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 &&
+          static_cast<uint32_t>(stats.wake_reason_cnt.cmd_event_wake_cnt_used) <=
+                  kMaxWakeReasonStatsArraySize);
+    stats.cmd_event_wake_cnt.resize(stats.wake_reason_cnt.cmd_event_wake_cnt_used);
+    stats.wake_reason_cnt.cmd_event_wake_cnt = nullptr;
+
+    CHECK(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used >= 0 &&
+          static_cast<uint32_t>(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used) <=
+                  kMaxWakeReasonStatsArraySize);
+    stats.driver_fw_local_wake_cnt.resize(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used);
+    stats.wake_reason_cnt.driver_fw_local_wake_cnt = nullptr;
+
+    return {status, stats};
+}
+
+wifi_error WifiLegacyHal::registerRingBufferCallbackHandler(
+        const std::string& iface_name, const on_ring_buffer_data_callback& on_user_data_callback) {
+    if (on_ring_buffer_data_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_ring_buffer_data_internal_callback = [on_user_data_callback](
+                                                    char* ring_name, char* buffer, int buffer_size,
+                                                    wifi_ring_buffer_status* status) {
+        if (status && buffer) {
+            std::vector<uint8_t> buffer_vector(reinterpret_cast<uint8_t*>(buffer),
+                                               reinterpret_cast<uint8_t*>(buffer) + buffer_size);
+            on_user_data_callback(ring_name, buffer_vector, *status);
+        }
+    };
+    wifi_error status = global_func_table_.wifi_set_log_handler(0, getIfaceHandle(iface_name),
+                                                                {onAsyncRingBufferData});
+    if (status != WIFI_SUCCESS) {
+        on_ring_buffer_data_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::deregisterRingBufferCallbackHandler(const std::string& iface_name) {
+    if (!on_ring_buffer_data_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_ring_buffer_data_internal_callback = nullptr;
+    return global_func_table_.wifi_reset_log_handler(0, getIfaceHandle(iface_name));
+}
+
+std::pair<wifi_error, std::vector<wifi_ring_buffer_status>> WifiLegacyHal::getRingBuffersStatus(
+        const std::string& iface_name) {
+    std::vector<wifi_ring_buffer_status> ring_buffers_status;
+    ring_buffers_status.resize(kMaxRingBuffers);
+    uint32_t num_rings = kMaxRingBuffers;
+    wifi_error status = global_func_table_.wifi_get_ring_buffers_status(
+            getIfaceHandle(iface_name), &num_rings, ring_buffers_status.data());
+    CHECK(num_rings <= kMaxRingBuffers);
+    ring_buffers_status.resize(num_rings);
+    return {status, std::move(ring_buffers_status)};
+}
+
+wifi_error WifiLegacyHal::startRingBufferLogging(const std::string& iface_name,
+                                                 const std::string& ring_name,
+                                                 uint32_t verbose_level, uint32_t max_interval_sec,
+                                                 uint32_t min_data_size) {
+    return global_func_table_.wifi_start_logging(getIfaceHandle(iface_name), verbose_level, 0,
+                                                 max_interval_sec, min_data_size,
+                                                 makeCharVec(ring_name).data());
+}
+
+wifi_error WifiLegacyHal::getRingBufferData(const std::string& iface_name,
+                                            const std::string& ring_name) {
+    return global_func_table_.wifi_get_ring_data(getIfaceHandle(iface_name),
+                                                 makeCharVec(ring_name).data());
+}
+
+wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler(
+        const std::string& iface_name, const on_error_alert_callback& on_user_alert_callback) {
+    if (on_error_alert_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_error_alert_internal_callback = [on_user_alert_callback](wifi_request_id id, char* buffer,
+                                                                int buffer_size, int err_code) {
+        if (buffer) {
+            CHECK(id == 0);
+            on_user_alert_callback(
+                    err_code,
+                    std::vector<uint8_t>(reinterpret_cast<uint8_t*>(buffer),
+                                         reinterpret_cast<uint8_t*>(buffer) + buffer_size));
+        }
+    };
+    wifi_error status = global_func_table_.wifi_set_alert_handler(0, getIfaceHandle(iface_name),
+                                                                  {onAsyncErrorAlert});
+    if (status != WIFI_SUCCESS) {
+        on_error_alert_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler(const std::string& iface_name) {
+    if (!on_error_alert_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_error_alert_internal_callback = nullptr;
+    return global_func_table_.wifi_reset_alert_handler(0, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::registerRadioModeChangeCallbackHandler(
+        const std::string& iface_name,
+        const on_radio_mode_change_callback& on_user_change_callback) {
+    if (on_radio_mode_change_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_radio_mode_change_internal_callback = [on_user_change_callback](
+                                                     wifi_request_id /* id */, uint32_t num_macs,
+                                                     wifi_mac_info* mac_infos_arr) {
+        if (num_macs > 0 && mac_infos_arr) {
+            std::vector<WifiMacInfo> mac_infos_vec;
+            for (uint32_t i = 0; i < num_macs; i++) {
+                WifiMacInfo mac_info;
+                mac_info.wlan_mac_id = mac_infos_arr[i].wlan_mac_id;
+                mac_info.mac_band = mac_infos_arr[i].mac_band;
+                for (int32_t j = 0; j < mac_infos_arr[i].num_iface; j++) {
+                    WifiIfaceInfo iface_info;
+                    iface_info.name = mac_infos_arr[i].iface_info[j].iface_name;
+                    iface_info.channel = mac_infos_arr[i].iface_info[j].channel;
+                    mac_info.iface_infos.push_back(iface_info);
+                }
+                mac_infos_vec.push_back(mac_info);
+            }
+            on_user_change_callback(mac_infos_vec);
+        }
+    };
+    wifi_error status = global_func_table_.wifi_set_radio_mode_change_handler(
+            0, getIfaceHandle(iface_name), {onAsyncRadioModeChange});
+    if (status != WIFI_SUCCESS) {
+        on_radio_mode_change_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::registerSubsystemRestartCallbackHandler(
+        const on_subsystem_restart_callback& on_restart_callback) {
+    if (on_subsystem_restart_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_subsystem_restart_internal_callback = [on_restart_callback](const char* error) {
+        on_restart_callback(error);
+    };
+    wifi_error status = global_func_table_.wifi_set_subsystem_restart_handler(
+            global_handle_, {onAsyncSubsystemRestart});
+    if (status != WIFI_SUCCESS) {
+        on_subsystem_restart_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::startRttRangeRequest(
+        const std::string& iface_name, wifi_request_id id,
+        const std::vector<wifi_rtt_config>& rtt_configs,
+        const on_rtt_results_callback& on_results_user_callback) {
+    if (on_rtt_results_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+
+    on_rtt_results_internal_callback = [on_results_user_callback](wifi_request_id id,
+                                                                  unsigned num_results,
+                                                                  wifi_rtt_result* rtt_results[]) {
+        if (num_results > 0 && !rtt_results) {
+            LOG(ERROR) << "Unexpected nullptr in RTT results";
+            return;
+        }
+        std::vector<const wifi_rtt_result*> rtt_results_vec;
+        std::copy_if(rtt_results, rtt_results + num_results, back_inserter(rtt_results_vec),
+                     [](wifi_rtt_result* rtt_result) { return rtt_result != nullptr; });
+        on_results_user_callback(id, rtt_results_vec);
+    };
+
+    std::vector<wifi_rtt_config> rtt_configs_internal(rtt_configs);
+    wifi_error status = global_func_table_.wifi_rtt_range_request(
+            id, getIfaceHandle(iface_name), rtt_configs.size(), rtt_configs_internal.data(),
+            {onAsyncRttResults});
+    if (status != WIFI_SUCCESS) {
+        on_rtt_results_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::cancelRttRangeRequest(
+        const std::string& iface_name, wifi_request_id id,
+        const std::vector<std::array<uint8_t, 6>>& mac_addrs) {
+    if (!on_rtt_results_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    static_assert(sizeof(mac_addr) == sizeof(std::array<uint8_t, 6>), "MAC address size mismatch");
+    // TODO: How do we handle partial cancels (i.e only a subset of enabled mac
+    // addressed are cancelled).
+    std::vector<std::array<uint8_t, 6>> mac_addrs_internal(mac_addrs);
+    wifi_error status = global_func_table_.wifi_rtt_range_cancel(
+            id, getIfaceHandle(iface_name), mac_addrs.size(),
+            reinterpret_cast<mac_addr*>(mac_addrs_internal.data()));
+    // If the request Id is wrong, don't stop the ongoing range request. Any
+    // other error should be treated as the end of rtt ranging.
+    if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
+        on_rtt_results_internal_callback = nullptr;
+    }
+    return status;
+}
+
+std::pair<wifi_error, wifi_rtt_capabilities> WifiLegacyHal::getRttCapabilities(
+        const std::string& iface_name) {
+    wifi_rtt_capabilities rtt_caps;
+    wifi_error status =
+            global_func_table_.wifi_get_rtt_capabilities(getIfaceHandle(iface_name), &rtt_caps);
+    return {status, rtt_caps};
+}
+
+std::pair<wifi_error, wifi_rtt_responder> WifiLegacyHal::getRttResponderInfo(
+        const std::string& iface_name) {
+    wifi_rtt_responder rtt_responder;
+    wifi_error status = global_func_table_.wifi_rtt_get_responder_info(getIfaceHandle(iface_name),
+                                                                       &rtt_responder);
+    return {status, rtt_responder};
+}
+
+wifi_error WifiLegacyHal::enableRttResponder(const std::string& iface_name, wifi_request_id id,
+                                             const wifi_channel_info& channel_hint,
+                                             uint32_t max_duration_secs,
+                                             const wifi_rtt_responder& info) {
+    wifi_rtt_responder info_internal(info);
+    return global_func_table_.wifi_enable_responder(id, getIfaceHandle(iface_name), channel_hint,
+                                                    max_duration_secs, &info_internal);
+}
+
+wifi_error WifiLegacyHal::disableRttResponder(const std::string& iface_name, wifi_request_id id) {
+    return global_func_table_.wifi_disable_responder(id, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::setRttLci(const std::string& iface_name, wifi_request_id id,
+                                    const wifi_lci_information& info) {
+    wifi_lci_information info_internal(info);
+    return global_func_table_.wifi_set_lci(id, getIfaceHandle(iface_name), &info_internal);
+}
+
+wifi_error WifiLegacyHal::setRttLcr(const std::string& iface_name, wifi_request_id id,
+                                    const wifi_lcr_information& info) {
+    wifi_lcr_information info_internal(info);
+    return global_func_table_.wifi_set_lcr(id, getIfaceHandle(iface_name), &info_internal);
+}
+
+wifi_error WifiLegacyHal::nanRegisterCallbackHandlers(const std::string& iface_name,
+                                                      const NanCallbackHandlers& user_callbacks) {
+    on_nan_notify_response_user_callback = user_callbacks.on_notify_response;
+    on_nan_event_publish_terminated_user_callback = user_callbacks.on_event_publish_terminated;
+    on_nan_event_match_user_callback = user_callbacks.on_event_match;
+    on_nan_event_match_expired_user_callback = user_callbacks.on_event_match_expired;
+    on_nan_event_subscribe_terminated_user_callback = user_callbacks.on_event_subscribe_terminated;
+    on_nan_event_followup_user_callback = user_callbacks.on_event_followup;
+    on_nan_event_disc_eng_event_user_callback = user_callbacks.on_event_disc_eng_event;
+    on_nan_event_disabled_user_callback = user_callbacks.on_event_disabled;
+    on_nan_event_tca_user_callback = user_callbacks.on_event_tca;
+    on_nan_event_beacon_sdf_payload_user_callback = user_callbacks.on_event_beacon_sdf_payload;
+    on_nan_event_data_path_request_user_callback = user_callbacks.on_event_data_path_request;
+    on_nan_event_data_path_confirm_user_callback = user_callbacks.on_event_data_path_confirm;
+    on_nan_event_data_path_end_user_callback = user_callbacks.on_event_data_path_end;
+    on_nan_event_transmit_follow_up_user_callback = user_callbacks.on_event_transmit_follow_up;
+    on_nan_event_range_request_user_callback = user_callbacks.on_event_range_request;
+    on_nan_event_range_report_user_callback = user_callbacks.on_event_range_report;
+    on_nan_event_schedule_update_user_callback = user_callbacks.on_event_schedule_update;
+
+    return global_func_table_.wifi_nan_register_handler(
+            getIfaceHandle(iface_name),
+            {onAysncNanNotifyResponse, onAysncNanEventPublishReplied,
+             onAysncNanEventPublishTerminated, onAysncNanEventMatch, onAysncNanEventMatchExpired,
+             onAysncNanEventSubscribeTerminated, onAysncNanEventFollowup,
+             onAysncNanEventDiscEngEvent, onAysncNanEventDisabled, onAysncNanEventTca,
+             onAysncNanEventBeaconSdfPayload, onAysncNanEventDataPathRequest,
+             onAysncNanEventDataPathConfirm, onAysncNanEventDataPathEnd,
+             onAysncNanEventTransmitFollowUp, onAysncNanEventRangeRequest,
+             onAysncNanEventRangeReport, onAsyncNanEventScheduleUpdate});
+}
+
+wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name, transaction_id id,
+                                           const NanEnableRequest& msg) {
+    NanEnableRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_enable_request(id, getIfaceHandle(iface_name),
+                                                      &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanDisableRequest(const std::string& iface_name, transaction_id id) {
+    return global_func_table_.wifi_nan_disable_request(id, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::nanPublishRequest(const std::string& iface_name, transaction_id id,
+                                            const NanPublishRequest& msg) {
+    NanPublishRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_publish_request(id, getIfaceHandle(iface_name),
+                                                       &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanPublishCancelRequest(const std::string& iface_name, transaction_id id,
+                                                  const NanPublishCancelRequest& msg) {
+    NanPublishCancelRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_publish_cancel_request(id, getIfaceHandle(iface_name),
+                                                              &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanSubscribeRequest(const std::string& iface_name, transaction_id id,
+                                              const NanSubscribeRequest& msg) {
+    NanSubscribeRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_subscribe_request(id, getIfaceHandle(iface_name),
+                                                         &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanSubscribeCancelRequest(const std::string& iface_name,
+                                                    transaction_id id,
+                                                    const NanSubscribeCancelRequest& msg) {
+    NanSubscribeCancelRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_subscribe_cancel_request(id, getIfaceHandle(iface_name),
+                                                                &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanTransmitFollowupRequest(const std::string& iface_name,
+                                                     transaction_id id,
+                                                     const NanTransmitFollowupRequest& msg) {
+    NanTransmitFollowupRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_transmit_followup_request(id, getIfaceHandle(iface_name),
+                                                                 &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanStatsRequest(const std::string& iface_name, transaction_id id,
+                                          const NanStatsRequest& msg) {
+    NanStatsRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_stats_request(id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanConfigRequest(const std::string& iface_name, transaction_id id,
+                                           const NanConfigRequest& msg) {
+    NanConfigRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_config_request(id, getIfaceHandle(iface_name),
+                                                      &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanTcaRequest(const std::string& iface_name, transaction_id id,
+                                        const NanTCARequest& msg) {
+    NanTCARequest msg_internal(msg);
+    return global_func_table_.wifi_nan_tca_request(id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanBeaconSdfPayloadRequest(const std::string& iface_name,
+                                                     transaction_id id,
+                                                     const NanBeaconSdfPayloadRequest& msg) {
+    NanBeaconSdfPayloadRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_beacon_sdf_payload_request(id, getIfaceHandle(iface_name),
+                                                                  &msg_internal);
+}
+
+std::pair<wifi_error, NanVersion> WifiLegacyHal::nanGetVersion() {
+    NanVersion version;
+    wifi_error status = global_func_table_.wifi_nan_get_version(global_handle_, &version);
+    return {status, version};
+}
+
+wifi_error WifiLegacyHal::nanGetCapabilities(const std::string& iface_name, transaction_id id) {
+    return global_func_table_.wifi_nan_get_capabilities(id, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::nanDataInterfaceCreate(const std::string& iface_name, transaction_id id,
+                                                 const std::string& data_iface_name) {
+    return global_func_table_.wifi_nan_data_interface_create(id, getIfaceHandle(iface_name),
+                                                             makeCharVec(data_iface_name).data());
+}
+
+wifi_error WifiLegacyHal::nanDataInterfaceDelete(const std::string& iface_name, transaction_id id,
+                                                 const std::string& data_iface_name) {
+    return global_func_table_.wifi_nan_data_interface_delete(id, getIfaceHandle(iface_name),
+                                                             makeCharVec(data_iface_name).data());
+}
+
+wifi_error WifiLegacyHal::nanDataRequestInitiator(const std::string& iface_name, transaction_id id,
+                                                  const NanDataPathInitiatorRequest& msg) {
+    NanDataPathInitiatorRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_data_request_initiator(id, getIfaceHandle(iface_name),
+                                                              &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanDataIndicationResponse(const std::string& iface_name,
+                                                    transaction_id id,
+                                                    const NanDataPathIndicationResponse& msg) {
+    NanDataPathIndicationResponse msg_internal(msg);
+    return global_func_table_.wifi_nan_data_indication_response(id, getIfaceHandle(iface_name),
+                                                                &msg_internal);
+}
+
+typedef struct {
+    u8 num_ndp_instances;
+    NanDataPathId ndp_instance_id;
+} NanDataPathEndSingleNdpIdRequest;
+
+wifi_error WifiLegacyHal::nanDataEnd(const std::string& iface_name, transaction_id id,
+                                     uint32_t ndpInstanceId) {
+    NanDataPathEndSingleNdpIdRequest msg;
+    msg.num_ndp_instances = 1;
+    msg.ndp_instance_id = ndpInstanceId;
+    wifi_error status = global_func_table_.wifi_nan_data_end(id, getIfaceHandle(iface_name),
+                                                             (NanDataPathEndRequest*)&msg);
+    return status;
+}
+
+wifi_error WifiLegacyHal::setCountryCode(const std::string& iface_name,
+                                         std::array<int8_t, 2> code) {
+    std::string code_str(code.data(), code.data() + code.size());
+    return global_func_table_.wifi_set_country_code(getIfaceHandle(iface_name), code_str.c_str());
+}
+
+wifi_error WifiLegacyHal::retrieveIfaceHandles() {
+    wifi_interface_handle* iface_handles = nullptr;
+    int num_iface_handles = 0;
+    wifi_error status =
+            global_func_table_.wifi_get_ifaces(global_handle_, &num_iface_handles, &iface_handles);
+    if (status != WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to enumerate interface handles";
+        return status;
+    }
+    iface_name_to_handle_.clear();
+    for (int i = 0; i < num_iface_handles; ++i) {
+        std::array<char, IFNAMSIZ> iface_name_arr = {};
+        status = global_func_table_.wifi_get_iface_name(iface_handles[i], iface_name_arr.data(),
+                                                        iface_name_arr.size());
+        if (status != WIFI_SUCCESS) {
+            LOG(WARNING) << "Failed to get interface handle name";
+            continue;
+        }
+        // Assuming the interface name is null terminated since the legacy HAL
+        // API does not return a size.
+        std::string iface_name(iface_name_arr.data());
+        LOG(INFO) << "Adding interface handle for " << iface_name;
+        iface_name_to_handle_[iface_name] = iface_handles[i];
+    }
+    return WIFI_SUCCESS;
+}
+
+wifi_interface_handle WifiLegacyHal::getIfaceHandle(const std::string& iface_name) {
+    const auto iface_handle_iter = iface_name_to_handle_.find(iface_name);
+    if (iface_handle_iter == iface_name_to_handle_.end()) {
+        LOG(ERROR) << "Unknown iface name: " << iface_name;
+        return nullptr;
+    }
+    return iface_handle_iter->second;
+}
+
+void WifiLegacyHal::runEventLoop() {
+    LOG(DEBUG) << "Starting legacy HAL event loop";
+    global_func_table_.wifi_event_loop(global_handle_);
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (!awaiting_event_loop_termination_) {
+        LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping";
+    }
+    LOG(DEBUG) << "Legacy HAL event loop terminated";
+    awaiting_event_loop_termination_ = false;
+    stop_wait_cv_.notify_one();
+}
+
+std::pair<wifi_error, std::vector<wifi_cached_scan_results>> WifiLegacyHal::getGscanCachedResults(
+        const std::string& iface_name) {
+    std::vector<wifi_cached_scan_results> cached_scan_results;
+    cached_scan_results.resize(kMaxCachedGscanResults);
+    int32_t num_results = 0;
+    wifi_error status = global_func_table_.wifi_get_cached_gscan_results(
+            getIfaceHandle(iface_name), true /* always flush */, cached_scan_results.size(),
+            cached_scan_results.data(), &num_results);
+    CHECK(num_results >= 0 && static_cast<uint32_t>(num_results) <= kMaxCachedGscanResults);
+    cached_scan_results.resize(num_results);
+    // Check for invalid IE lengths in these cached scan results and correct it.
+    for (auto& cached_scan_result : cached_scan_results) {
+        int num_scan_results = cached_scan_result.num_results;
+        for (int i = 0; i < num_scan_results; i++) {
+            auto& scan_result = cached_scan_result.results[i];
+            if (scan_result.ie_length > 0) {
+                LOG(DEBUG) << "Cached scan result has non-zero IE length " << scan_result.ie_length;
+                scan_result.ie_length = 0;
+            }
+        }
+    }
+    return {status, std::move(cached_scan_results)};
+}
+
+wifi_error WifiLegacyHal::createVirtualInterface(const std::string& ifname,
+                                                 wifi_interface_type iftype) {
+    // Create the interface if it doesn't exist. If interface already exist,
+    // Vendor Hal should return WIFI_SUCCESS.
+    wifi_error status = global_func_table_.wifi_virtual_interface_create(global_handle_,
+                                                                         ifname.c_str(), iftype);
+    return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status);
+}
+
+wifi_error WifiLegacyHal::deleteVirtualInterface(const std::string& ifname) {
+    // Delete the interface if it was created dynamically.
+    wifi_error status =
+            global_func_table_.wifi_virtual_interface_delete(global_handle_, ifname.c_str());
+    return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status);
+}
+
+wifi_error WifiLegacyHal::handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname,
+                                                                     wifi_error status) {
+    if (status == WIFI_SUCCESS) {
+        // refresh list of handlers now.
+        status = retrieveIfaceHandles();
+    } else if (status == WIFI_ERROR_NOT_SUPPORTED) {
+        // Vendor hal does not implement this API. Such vendor implementations
+        // are expected to create / delete interface by other means.
+
+        // check if interface exists.
+        if (if_nametoindex(ifname.c_str())) {
+            status = retrieveIfaceHandles();
+        }
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::getSupportedIfaceName(uint32_t iface_type, std::string& ifname) {
+    std::array<char, IFNAMSIZ> buffer;
+
+    wifi_error res = global_func_table_.wifi_get_supported_iface_name(
+            global_handle_, (uint32_t)iface_type, buffer.data(), buffer.size());
+    if (res == WIFI_SUCCESS) ifname = buffer.data();
+
+    return res;
+}
+
+wifi_error WifiLegacyHal::multiStaSetPrimaryConnection(const std::string& ifname) {
+    return global_func_table_.wifi_multi_sta_set_primary_connection(global_handle_,
+                                                                    getIfaceHandle(ifname));
+}
+
+wifi_error WifiLegacyHal::multiStaSetUseCase(wifi_multi_sta_use_case use_case) {
+    return global_func_table_.wifi_multi_sta_set_use_case(global_handle_, use_case);
+}
+
+wifi_error WifiLegacyHal::setCoexUnsafeChannels(
+        std::vector<wifi_coex_unsafe_channel> unsafe_channels, uint32_t restrictions) {
+    return global_func_table_.wifi_set_coex_unsafe_channels(global_handle_, unsafe_channels.size(),
+                                                            unsafe_channels.data(), restrictions);
+}
+
+wifi_error WifiLegacyHal::setVoipMode(const std::string& iface_name, wifi_voip_mode mode) {
+    return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name), mode);
+}
+
+wifi_error WifiLegacyHal::twtRegisterHandler(const std::string& iface_name,
+                                             const TwtCallbackHandlers& user_callbacks) {
+    on_twt_event_setup_response_callback = user_callbacks.on_setup_response;
+    on_twt_event_teardown_completion_callback = user_callbacks.on_teardown_completion;
+    on_twt_event_info_frame_received_callback = user_callbacks.on_info_frame_received;
+    on_twt_event_device_notify_callback = user_callbacks.on_device_notify;
+
+    return global_func_table_.wifi_twt_register_handler(
+            getIfaceHandle(iface_name),
+            {onAsyncTwtEventSetupResponse, onAsyncTwtEventTeardownCompletion,
+             onAsyncTwtEventInfoFrameReceived, onAsyncTwtEventDeviceNotify});
+}
+
+std::pair<wifi_error, TwtCapabilitySet> WifiLegacyHal::twtGetCapability(
+        const std::string& iface_name) {
+    TwtCapabilitySet capSet;
+    wifi_error status =
+            global_func_table_.wifi_twt_get_capability(getIfaceHandle(iface_name), &capSet);
+    return {status, capSet};
+}
+
+wifi_error WifiLegacyHal::twtSetupRequest(const std::string& iface_name,
+                                          const TwtSetupRequest& msg) {
+    TwtSetupRequest msgInternal(msg);
+    return global_func_table_.wifi_twt_setup_request(getIfaceHandle(iface_name), &msgInternal);
+}
+
+wifi_error WifiLegacyHal::twtTearDownRequest(const std::string& iface_name,
+                                             const TwtTeardownRequest& msg) {
+    TwtTeardownRequest msgInternal(msg);
+    return global_func_table_.wifi_twt_teardown_request(getIfaceHandle(iface_name), &msgInternal);
+}
+
+wifi_error WifiLegacyHal::twtInfoFrameRequest(const std::string& iface_name,
+                                              const TwtInfoFrameRequest& msg) {
+    TwtInfoFrameRequest msgInternal(msg);
+    return global_func_table_.wifi_twt_info_frame_request(getIfaceHandle(iface_name), &msgInternal);
+}
+
+std::pair<wifi_error, TwtStats> WifiLegacyHal::twtGetStats(const std::string& iface_name,
+                                                           uint8_t configId) {
+    TwtStats stats;
+    wifi_error status =
+            global_func_table_.wifi_twt_get_stats(getIfaceHandle(iface_name), configId, &stats);
+    return {status, stats};
+}
+
+wifi_error WifiLegacyHal::twtClearStats(const std::string& iface_name, uint8_t configId) {
+    return global_func_table_.wifi_twt_clear_stats(getIfaceHandle(iface_name), configId);
+}
+
+wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name, uint32_t multiplier) {
+    return global_func_table_.wifi_set_dtim_config(getIfaceHandle(iface_name), multiplier);
+}
+
+std::pair<wifi_error, std::vector<wifi_usable_channel>> WifiLegacyHal::getUsableChannels(
+        uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask) {
+    std::vector<wifi_usable_channel> channels;
+    channels.resize(kMaxWifiUsableChannels);
+    uint32_t size = 0;
+    wifi_error status = global_func_table_.wifi_get_usable_channels(
+            global_handle_, band_mask, iface_mode_mask, filter_mask, channels.size(), &size,
+            reinterpret_cast<wifi_usable_channel*>(channels.data()));
+    CHECK(size >= 0 && size <= kMaxWifiUsableChannels);
+    channels.resize(size);
+    return {status, std::move(channels)};
+}
+
+wifi_error WifiLegacyHal::triggerSubsystemRestart() {
+    return global_func_table_.wifi_trigger_subsystem_restart(global_handle_);
+}
+
+void WifiLegacyHal::invalidate() {
+    global_handle_ = nullptr;
+    iface_name_to_handle_.clear();
+    on_driver_memory_dump_internal_callback = nullptr;
+    on_firmware_memory_dump_internal_callback = nullptr;
+    on_gscan_event_internal_callback = nullptr;
+    on_gscan_full_result_internal_callback = nullptr;
+    on_link_layer_stats_result_internal_callback = nullptr;
+    on_rssi_threshold_breached_internal_callback = nullptr;
+    on_ring_buffer_data_internal_callback = nullptr;
+    on_error_alert_internal_callback = nullptr;
+    on_radio_mode_change_internal_callback = nullptr;
+    on_subsystem_restart_internal_callback = nullptr;
+    on_rtt_results_internal_callback = nullptr;
+    on_nan_notify_response_user_callback = nullptr;
+    on_nan_event_publish_terminated_user_callback = nullptr;
+    on_nan_event_match_user_callback = nullptr;
+    on_nan_event_match_expired_user_callback = nullptr;
+    on_nan_event_subscribe_terminated_user_callback = nullptr;
+    on_nan_event_followup_user_callback = nullptr;
+    on_nan_event_disc_eng_event_user_callback = nullptr;
+    on_nan_event_disabled_user_callback = nullptr;
+    on_nan_event_tca_user_callback = nullptr;
+    on_nan_event_beacon_sdf_payload_user_callback = nullptr;
+    on_nan_event_data_path_request_user_callback = nullptr;
+    on_nan_event_data_path_confirm_user_callback = nullptr;
+    on_nan_event_data_path_end_user_callback = nullptr;
+    on_nan_event_transmit_follow_up_user_callback = nullptr;
+    on_nan_event_range_request_user_callback = nullptr;
+    on_nan_event_range_report_user_callback = nullptr;
+    on_nan_event_schedule_update_user_callback = nullptr;
+    on_twt_event_setup_response_callback = nullptr;
+    on_twt_event_teardown_completion_callback = nullptr;
+    on_twt_event_info_frame_received_callback = nullptr;
+    on_twt_event_device_notify_callback = nullptr;
+}
+
+}  // namespace legacy_hal
+}  // namespace implementation
+}  // namespace V1_6
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.5/default/wifi_legacy_hal.h b/wifi/1.6/default/wifi_legacy_hal.h
similarity index 73%
rename from wifi/1.5/default/wifi_legacy_hal.h
rename to wifi/1.6/default/wifi_legacy_hal.h
index 2bb7631..d87242c 100644
--- a/wifi/1.5/default/wifi_legacy_hal.h
+++ b/wifi/1.6/default/wifi_legacy_hal.h
@@ -29,7 +29,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 // This is in a separate namespace to prevent typename conflicts between
 // the legacy HAL types and the HIDL interface types.
@@ -366,63 +366,53 @@
 // NAN response and event callbacks struct.
 struct NanCallbackHandlers {
     // NotifyResponse invoked to notify the status of the Request.
-    std::function<void(transaction_id, const NanResponseMsg&)>
-        on_notify_response;
+    std::function<void(transaction_id, const NanResponseMsg&)> on_notify_response;
     // Various event callbacks.
-    std::function<void(const NanPublishTerminatedInd&)>
-        on_event_publish_terminated;
+    std::function<void(const NanPublishTerminatedInd&)> on_event_publish_terminated;
     std::function<void(const NanMatchInd&)> on_event_match;
     std::function<void(const NanMatchExpiredInd&)> on_event_match_expired;
-    std::function<void(const NanSubscribeTerminatedInd&)>
-        on_event_subscribe_terminated;
+    std::function<void(const NanSubscribeTerminatedInd&)> on_event_subscribe_terminated;
     std::function<void(const NanFollowupInd&)> on_event_followup;
     std::function<void(const NanDiscEngEventInd&)> on_event_disc_eng_event;
     std::function<void(const NanDisabledInd&)> on_event_disabled;
     std::function<void(const NanTCAInd&)> on_event_tca;
-    std::function<void(const NanBeaconSdfPayloadInd&)>
-        on_event_beacon_sdf_payload;
-    std::function<void(const NanDataPathRequestInd&)>
-        on_event_data_path_request;
-    std::function<void(const NanDataPathConfirmInd&)>
-        on_event_data_path_confirm;
+    std::function<void(const NanBeaconSdfPayloadInd&)> on_event_beacon_sdf_payload;
+    std::function<void(const NanDataPathRequestInd&)> on_event_data_path_request;
+    std::function<void(const NanDataPathConfirmInd&)> on_event_data_path_confirm;
     std::function<void(const NanDataPathEndInd&)> on_event_data_path_end;
-    std::function<void(const NanTransmitFollowupInd&)>
-        on_event_transmit_follow_up;
+    std::function<void(const NanTransmitFollowupInd&)> on_event_transmit_follow_up;
     std::function<void(const NanRangeRequestInd&)> on_event_range_request;
     std::function<void(const NanRangeReportInd&)> on_event_range_report;
-    std::function<void(const NanDataPathScheduleUpdateInd&)>
-        on_event_schedule_update;
+    std::function<void(const NanDataPathScheduleUpdateInd&)> on_event_schedule_update;
 };
 
 // Full scan results contain IE info and are hence passed by reference, to
 // preserve the variable length array member |ie_data|. Callee must not retain
 // the pointer.
 using on_gscan_full_result_callback =
-    std::function<void(wifi_request_id, const wifi_scan_result*, uint32_t)>;
+        std::function<void(wifi_request_id, const wifi_scan_result*, uint32_t)>;
 // These scan results don't contain any IE info, so no need to pass by
 // reference.
-using on_gscan_results_callback = std::function<void(
-    wifi_request_id, const std::vector<wifi_cached_scan_results>&)>;
+using on_gscan_results_callback =
+        std::function<void(wifi_request_id, const std::vector<wifi_cached_scan_results>&)>;
 
 // Invoked when the rssi value breaches the thresholds set.
 using on_rssi_threshold_breached_callback =
-    std::function<void(wifi_request_id, std::array<uint8_t, 6>, int8_t)>;
+        std::function<void(wifi_request_id, std::array<uint8_t, 6>, int8_t)>;
 
 // Callback for RTT range request results.
 // Rtt results contain IE info and are hence passed by reference, to
 // preserve the |LCI| and |LCR| pointers. Callee must not retain
 // the pointer.
-using on_rtt_results_callback = std::function<void(
-    wifi_request_id, const std::vector<const wifi_rtt_result*>&)>;
+using on_rtt_results_callback =
+        std::function<void(wifi_request_id, const std::vector<const wifi_rtt_result*>&)>;
 
 // Callback for ring buffer data.
-using on_ring_buffer_data_callback =
-    std::function<void(const std::string&, const std::vector<uint8_t>&,
-                       const wifi_ring_buffer_status&)>;
+using on_ring_buffer_data_callback = std::function<void(
+        const std::string&, const std::vector<uint8_t>&, const wifi_ring_buffer_status&)>;
 
 // Callback for alerts.
-using on_error_alert_callback =
-    std::function<void(int32_t, const std::vector<uint8_t>&)>;
+using on_error_alert_callback = std::function<void(int32_t, const std::vector<uint8_t>&)>;
 
 // Callback for subsystem restart
 using on_subsystem_restart_callback = std::function<void(const std::string&)>;
@@ -443,8 +433,7 @@
 } WifiMacInfo;
 
 // Callback for radio mode change
-using on_radio_mode_change_callback =
-    std::function<void(const std::vector<WifiMacInfo>&)>;
+using on_radio_mode_change_callback = std::function<void(const std::vector<WifiMacInfo>&)>;
 
 // TWT response and event callbacks struct.
 struct TwtCallbackHandlers {
@@ -466,9 +455,9 @@
  * object and will be valid for the lifetime of the process.
  */
 class WifiLegacyHal {
-   public:
-    WifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
-                  const wifi_hal_fn& fn, bool is_primary);
+  public:
+    WifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool, const wifi_hal_fn& fn,
+                  bool is_primary);
     virtual ~WifiLegacyHal() = default;
 
     // Initialize the legacy HAL function table.
@@ -483,26 +472,22 @@
     // Checks if legacy HAL has successfully started
     bool isStarted();
     // Wrappers for all the functions in the legacy HAL function table.
-    virtual std::pair<wifi_error, std::string> getDriverVersion(
-        const std::string& iface_name);
-    virtual std::pair<wifi_error, std::string> getFirmwareVersion(
-        const std::string& iface_name);
+    virtual std::pair<wifi_error, std::string> getDriverVersion(const std::string& iface_name);
+    virtual std::pair<wifi_error, std::string> getFirmwareVersion(const std::string& iface_name);
     std::pair<wifi_error, std::vector<uint8_t>> requestDriverMemoryDump(
-        const std::string& iface_name);
+            const std::string& iface_name);
     std::pair<wifi_error, std::vector<uint8_t>> requestFirmwareMemoryDump(
-        const std::string& iface_name);
-    std::pair<wifi_error, uint64_t> getSupportedFeatureSet(
-        const std::string& iface_name);
+            const std::string& iface_name);
+    std::pair<wifi_error, uint64_t> getSupportedFeatureSet(const std::string& iface_name);
     // APF functions.
     std::pair<wifi_error, PacketFilterCapabilities> getPacketFilterCapabilities(
-        const std::string& iface_name);
-    wifi_error setPacketFilter(const std::string& iface_name,
-                               const std::vector<uint8_t>& program);
+            const std::string& iface_name);
+    wifi_error setPacketFilter(const std::string& iface_name, const std::vector<uint8_t>& program);
     std::pair<wifi_error, std::vector<uint8_t>> readApfPacketFilterData(
-        const std::string& iface_name);
+            const std::string& iface_name);
     // Gscan functions.
     std::pair<wifi_error, wifi_gscan_capabilities> getGscanCapabilities(
-        const std::string& iface_name);
+            const std::string& iface_name);
     // These API's provides a simplified interface over the legacy Gscan API's:
     // a) All scan events from the legacy HAL API other than the
     //    |WIFI_SCAN_FAILED| are treated as notification of results.
@@ -514,162 +499,121 @@
     //    triggers the externally provided |on_failure_user_callback|.
     // c) Full scan result event triggers the externally provided
     //    |on_full_result_user_callback|.
-    wifi_error startGscan(
-        const std::string& iface_name, wifi_request_id id,
-        const wifi_scan_cmd_params& params,
-        const std::function<void(wifi_request_id)>& on_failure_callback,
-        const on_gscan_results_callback& on_results_callback,
-        const on_gscan_full_result_callback& on_full_result_callback);
+    wifi_error startGscan(const std::string& iface_name, wifi_request_id id,
+                          const wifi_scan_cmd_params& params,
+                          const std::function<void(wifi_request_id)>& on_failure_callback,
+                          const on_gscan_results_callback& on_results_callback,
+                          const on_gscan_full_result_callback& on_full_result_callback);
     wifi_error stopGscan(const std::string& iface_name, wifi_request_id id);
     std::pair<wifi_error, std::vector<uint32_t>> getValidFrequenciesForBand(
-        const std::string& iface_name, wifi_band band);
+            const std::string& iface_name, wifi_band band);
     virtual wifi_error setDfsFlag(const std::string& iface_name, bool dfs_on);
     // Link layer stats functions.
     wifi_error enableLinkLayerStats(const std::string& iface_name, bool debug);
     wifi_error disableLinkLayerStats(const std::string& iface_name);
-    std::pair<wifi_error, LinkLayerStats> getLinkLayerStats(
-        const std::string& iface_name);
+    std::pair<wifi_error, LinkLayerStats> getLinkLayerStats(const std::string& iface_name);
     // RSSI monitor functions.
-    wifi_error startRssiMonitoring(const std::string& iface_name,
-                                   wifi_request_id id, int8_t max_rssi,
-                                   int8_t min_rssi,
-                                   const on_rssi_threshold_breached_callback&
-                                       on_threshold_breached_callback);
-    wifi_error stopRssiMonitoring(const std::string& iface_name,
-                                  wifi_request_id id);
+    wifi_error startRssiMonitoring(
+            const std::string& iface_name, wifi_request_id id, int8_t max_rssi, int8_t min_rssi,
+            const on_rssi_threshold_breached_callback& on_threshold_breached_callback);
+    wifi_error stopRssiMonitoring(const std::string& iface_name, wifi_request_id id);
     std::pair<wifi_error, wifi_roaming_capabilities> getRoamingCapabilities(
-        const std::string& iface_name);
-    wifi_error configureRoaming(const std::string& iface_name,
-                                const wifi_roaming_config& config);
-    wifi_error enableFirmwareRoaming(const std::string& iface_name,
-                                     fw_roaming_state_t state);
+            const std::string& iface_name);
+    wifi_error configureRoaming(const std::string& iface_name, const wifi_roaming_config& config);
+    wifi_error enableFirmwareRoaming(const std::string& iface_name, fw_roaming_state_t state);
     wifi_error configureNdOffload(const std::string& iface_name, bool enable);
-    wifi_error startSendingOffloadedPacket(
-        const std::string& iface_name, uint32_t cmd_id, uint16_t ether_type,
-        const std::vector<uint8_t>& ip_packet_data,
-        const std::array<uint8_t, 6>& src_address,
-        const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms);
-    wifi_error stopSendingOffloadedPacket(const std::string& iface_name,
-                                          uint32_t cmd_id);
+    wifi_error startSendingOffloadedPacket(const std::string& iface_name, uint32_t cmd_id,
+                                           uint16_t ether_type,
+                                           const std::vector<uint8_t>& ip_packet_data,
+                                           const std::array<uint8_t, 6>& src_address,
+                                           const std::array<uint8_t, 6>& dst_address,
+                                           uint32_t period_in_ms);
+    wifi_error stopSendingOffloadedPacket(const std::string& iface_name, uint32_t cmd_id);
     virtual wifi_error selectTxPowerScenario(const std::string& iface_name,
                                              wifi_power_scenario scenario);
     virtual wifi_error resetTxPowerScenario(const std::string& iface_name);
-    wifi_error setLatencyMode(const std::string& iface_name,
-                              wifi_latency_mode mode);
-    wifi_error setThermalMitigationMode(wifi_thermal_mode mode,
-                                        uint32_t completion_window);
+    wifi_error setLatencyMode(const std::string& iface_name, wifi_latency_mode mode);
+    wifi_error setThermalMitigationMode(wifi_thermal_mode mode, uint32_t completion_window);
     wifi_error setDscpToAccessCategoryMapping(uint32_t start, uint32_t end,
                                               uint32_t access_category);
     wifi_error resetDscpToAccessCategoryMapping();
     // Logger/debug functions.
-    std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet(
-        const std::string& iface_name);
+    std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet(const std::string& iface_name);
     wifi_error startPktFateMonitoring(const std::string& iface_name);
-    std::pair<wifi_error, std::vector<wifi_tx_report>> getTxPktFates(
-        const std::string& iface_name);
-    std::pair<wifi_error, std::vector<wifi_rx_report>> getRxPktFates(
-        const std::string& iface_name);
-    std::pair<wifi_error, WakeReasonStats> getWakeReasonStats(
-        const std::string& iface_name);
+    std::pair<wifi_error, std::vector<wifi_tx_report>> getTxPktFates(const std::string& iface_name);
+    std::pair<wifi_error, std::vector<wifi_rx_report>> getRxPktFates(const std::string& iface_name);
+    std::pair<wifi_error, WakeReasonStats> getWakeReasonStats(const std::string& iface_name);
     wifi_error registerRingBufferCallbackHandler(
-        const std::string& iface_name,
-        const on_ring_buffer_data_callback& on_data_callback);
-    wifi_error deregisterRingBufferCallbackHandler(
-        const std::string& iface_name);
+            const std::string& iface_name, const on_ring_buffer_data_callback& on_data_callback);
+    wifi_error deregisterRingBufferCallbackHandler(const std::string& iface_name);
     wifi_error registerSubsystemRestartCallbackHandler(
-        const on_subsystem_restart_callback& on_restart_callback);
-    std::pair<wifi_error, std::vector<wifi_ring_buffer_status>>
-    getRingBuffersStatus(const std::string& iface_name);
-    wifi_error startRingBufferLogging(const std::string& iface_name,
-                                      const std::string& ring_name,
-                                      uint32_t verbose_level,
-                                      uint32_t max_interval_sec,
+            const on_subsystem_restart_callback& on_restart_callback);
+    std::pair<wifi_error, std::vector<wifi_ring_buffer_status>> getRingBuffersStatus(
+            const std::string& iface_name);
+    wifi_error startRingBufferLogging(const std::string& iface_name, const std::string& ring_name,
+                                      uint32_t verbose_level, uint32_t max_interval_sec,
                                       uint32_t min_data_size);
-    wifi_error getRingBufferData(const std::string& iface_name,
-                                 const std::string& ring_name);
-    wifi_error registerErrorAlertCallbackHandler(
-        const std::string& iface_name,
-        const on_error_alert_callback& on_alert_callback);
-    wifi_error deregisterErrorAlertCallbackHandler(
-        const std::string& iface_name);
+    wifi_error getRingBufferData(const std::string& iface_name, const std::string& ring_name);
+    wifi_error registerErrorAlertCallbackHandler(const std::string& iface_name,
+                                                 const on_error_alert_callback& on_alert_callback);
+    wifi_error deregisterErrorAlertCallbackHandler(const std::string& iface_name);
     // Radio mode functions.
     virtual wifi_error registerRadioModeChangeCallbackHandler(
-        const std::string& iface_name,
-        const on_radio_mode_change_callback& on_user_change_callback);
+            const std::string& iface_name,
+            const on_radio_mode_change_callback& on_user_change_callback);
     // RTT functions.
-    wifi_error startRttRangeRequest(
-        const std::string& iface_name, wifi_request_id id,
-        const std::vector<wifi_rtt_config>& rtt_configs,
-        const on_rtt_results_callback& on_results_callback);
-    wifi_error cancelRttRangeRequest(
-        const std::string& iface_name, wifi_request_id id,
-        const std::vector<std::array<uint8_t, 6>>& mac_addrs);
-    std::pair<wifi_error, wifi_rtt_capabilities> getRttCapabilities(
-        const std::string& iface_name);
-    std::pair<wifi_error, wifi_rtt_responder> getRttResponderInfo(
-        const std::string& iface_name);
-    wifi_error enableRttResponder(const std::string& iface_name,
-                                  wifi_request_id id,
-                                  const wifi_channel_info& channel_hint,
-                                  uint32_t max_duration_secs,
+    wifi_error startRttRangeRequest(const std::string& iface_name, wifi_request_id id,
+                                    const std::vector<wifi_rtt_config>& rtt_configs,
+                                    const on_rtt_results_callback& on_results_callback);
+    wifi_error cancelRttRangeRequest(const std::string& iface_name, wifi_request_id id,
+                                     const std::vector<std::array<uint8_t, 6>>& mac_addrs);
+    std::pair<wifi_error, wifi_rtt_capabilities> getRttCapabilities(const std::string& iface_name);
+    std::pair<wifi_error, wifi_rtt_responder> getRttResponderInfo(const std::string& iface_name);
+    wifi_error enableRttResponder(const std::string& iface_name, wifi_request_id id,
+                                  const wifi_channel_info& channel_hint, uint32_t max_duration_secs,
                                   const wifi_rtt_responder& info);
-    wifi_error disableRttResponder(const std::string& iface_name,
-                                   wifi_request_id id);
+    wifi_error disableRttResponder(const std::string& iface_name, wifi_request_id id);
     wifi_error setRttLci(const std::string& iface_name, wifi_request_id id,
                          const wifi_lci_information& info);
     wifi_error setRttLcr(const std::string& iface_name, wifi_request_id id,
                          const wifi_lcr_information& info);
     // NAN functions.
-    virtual wifi_error nanRegisterCallbackHandlers(
-        const std::string& iface_name, const NanCallbackHandlers& callbacks);
-    wifi_error nanEnableRequest(const std::string& iface_name,
-                                transaction_id id, const NanEnableRequest& msg);
-    virtual wifi_error nanDisableRequest(const std::string& iface_name,
-                                         transaction_id id);
-    wifi_error nanPublishRequest(const std::string& iface_name,
-                                 transaction_id id,
+    virtual wifi_error nanRegisterCallbackHandlers(const std::string& iface_name,
+                                                   const NanCallbackHandlers& callbacks);
+    wifi_error nanEnableRequest(const std::string& iface_name, transaction_id id,
+                                const NanEnableRequest& msg);
+    virtual wifi_error nanDisableRequest(const std::string& iface_name, transaction_id id);
+    wifi_error nanPublishRequest(const std::string& iface_name, transaction_id id,
                                  const NanPublishRequest& msg);
-    wifi_error nanPublishCancelRequest(const std::string& iface_name,
-                                       transaction_id id,
+    wifi_error nanPublishCancelRequest(const std::string& iface_name, transaction_id id,
                                        const NanPublishCancelRequest& msg);
-    wifi_error nanSubscribeRequest(const std::string& iface_name,
-                                   transaction_id id,
+    wifi_error nanSubscribeRequest(const std::string& iface_name, transaction_id id,
                                    const NanSubscribeRequest& msg);
-    wifi_error nanSubscribeCancelRequest(const std::string& iface_name,
-                                         transaction_id id,
+    wifi_error nanSubscribeCancelRequest(const std::string& iface_name, transaction_id id,
                                          const NanSubscribeCancelRequest& msg);
-    wifi_error nanTransmitFollowupRequest(
-        const std::string& iface_name, transaction_id id,
-        const NanTransmitFollowupRequest& msg);
+    wifi_error nanTransmitFollowupRequest(const std::string& iface_name, transaction_id id,
+                                          const NanTransmitFollowupRequest& msg);
     wifi_error nanStatsRequest(const std::string& iface_name, transaction_id id,
                                const NanStatsRequest& msg);
-    wifi_error nanConfigRequest(const std::string& iface_name,
-                                transaction_id id, const NanConfigRequest& msg);
+    wifi_error nanConfigRequest(const std::string& iface_name, transaction_id id,
+                                const NanConfigRequest& msg);
     wifi_error nanTcaRequest(const std::string& iface_name, transaction_id id,
                              const NanTCARequest& msg);
-    wifi_error nanBeaconSdfPayloadRequest(
-        const std::string& iface_name, transaction_id id,
-        const NanBeaconSdfPayloadRequest& msg);
+    wifi_error nanBeaconSdfPayloadRequest(const std::string& iface_name, transaction_id id,
+                                          const NanBeaconSdfPayloadRequest& msg);
     std::pair<wifi_error, NanVersion> nanGetVersion();
-    wifi_error nanGetCapabilities(const std::string& iface_name,
-                                  transaction_id id);
-    wifi_error nanDataInterfaceCreate(const std::string& iface_name,
-                                      transaction_id id,
+    wifi_error nanGetCapabilities(const std::string& iface_name, transaction_id id);
+    wifi_error nanDataInterfaceCreate(const std::string& iface_name, transaction_id id,
                                       const std::string& data_iface_name);
-    virtual wifi_error nanDataInterfaceDelete(
-        const std::string& iface_name, transaction_id id,
-        const std::string& data_iface_name);
-    wifi_error nanDataRequestInitiator(const std::string& iface_name,
-                                       transaction_id id,
+    virtual wifi_error nanDataInterfaceDelete(const std::string& iface_name, transaction_id id,
+                                              const std::string& data_iface_name);
+    wifi_error nanDataRequestInitiator(const std::string& iface_name, transaction_id id,
                                        const NanDataPathInitiatorRequest& msg);
-    wifi_error nanDataIndicationResponse(
-        const std::string& iface_name, transaction_id id,
-        const NanDataPathIndicationResponse& msg);
-    wifi_error nanDataEnd(const std::string& iface_name, transaction_id id,
-                          uint32_t ndpInstanceId);
+    wifi_error nanDataIndicationResponse(const std::string& iface_name, transaction_id id,
+                                         const NanDataPathIndicationResponse& msg);
+    wifi_error nanDataEnd(const std::string& iface_name, transaction_id id, uint32_t ndpInstanceId);
     // AP functions.
-    wifi_error setCountryCode(const std::string& iface_name,
-                              std::array<int8_t, 2> code);
+    wifi_error setCountryCode(const std::string& iface_name, std::array<int8_t, 2> code);
 
     // interface functions.
     virtual wifi_error createVirtualInterface(const std::string& ifname,
@@ -682,43 +626,36 @@
     virtual wifi_error multiStaSetUseCase(wifi_multi_sta_use_case use_case);
 
     // Coex functions.
-    virtual wifi_error setCoexUnsafeChannels(
-        std::vector<wifi_coex_unsafe_channel> unsafe_channels,
-        uint32_t restrictions);
+    virtual wifi_error setCoexUnsafeChannels(std::vector<wifi_coex_unsafe_channel> unsafe_channels,
+                                             uint32_t restrictions);
 
     wifi_error setVoipMode(const std::string& iface_name, wifi_voip_mode mode);
 
     wifi_error twtRegisterHandler(const std::string& iface_name,
                                   const TwtCallbackHandlers& handler);
 
-    std::pair<wifi_error, TwtCapabilitySet> twtGetCapability(
-        const std::string& iface_name);
+    std::pair<wifi_error, TwtCapabilitySet> twtGetCapability(const std::string& iface_name);
 
-    wifi_error twtSetupRequest(const std::string& iface_name,
-                               const TwtSetupRequest& msg);
+    wifi_error twtSetupRequest(const std::string& iface_name, const TwtSetupRequest& msg);
 
-    wifi_error twtTearDownRequest(const std::string& iface_name,
-                                  const TwtTeardownRequest& msg);
+    wifi_error twtTearDownRequest(const std::string& iface_name, const TwtTeardownRequest& msg);
 
-    wifi_error twtInfoFrameRequest(const std::string& iface_name,
-                                   const TwtInfoFrameRequest& msg);
+    wifi_error twtInfoFrameRequest(const std::string& iface_name, const TwtInfoFrameRequest& msg);
 
-    std::pair<wifi_error, TwtStats> twtGetStats(const std::string& iface_name,
-                                                uint8_t configId);
+    std::pair<wifi_error, TwtStats> twtGetStats(const std::string& iface_name, uint8_t configId);
 
     wifi_error twtClearStats(const std::string& iface_name, uint8_t configId);
 
-    wifi_error setDtimConfig(const std::string& iface_name,
-                             uint32_t multiplier);
+    wifi_error setDtimConfig(const std::string& iface_name, uint32_t multiplier);
 
     // Retrieve the list of usable channels in the requested bands
     // for the requested modes
     std::pair<wifi_error, std::vector<wifi_usable_channel>> getUsableChannels(
-        uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask);
+            uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask);
 
     wifi_error triggerSubsystemRestart();
 
-   private:
+  private:
     // Retrieve interface handles for all the available interfaces.
     wifi_error retrieveIfaceHandles();
     wifi_interface_handle getIfaceHandle(const std::string& iface_name);
@@ -726,12 +663,12 @@
     void runEventLoop();
     // Retrieve the cached gscan results to pass the results back to the
     // external callbacks.
-    std::pair<wifi_error, std::vector<wifi_cached_scan_results>>
-    getGscanCachedResults(const std::string& iface_name);
+    std::pair<wifi_error, std::vector<wifi_cached_scan_results>> getGscanCachedResults(
+            const std::string& iface_name);
     void invalidate();
     // Handles wifi (error) status of Virtual interface create/delete
-    wifi_error handleVirtualInterfaceCreateOrDeleteStatus(
-        const std::string& ifname, wifi_error status);
+    wifi_error handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname,
+                                                          wifi_error status);
 
     // Global function table of legacy HAL.
     wifi_hal_fn global_func_table_;
@@ -755,7 +692,7 @@
 
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_legacy_hal_factory.cpp b/wifi/1.6/default/wifi_legacy_hal_factory.cpp
similarity index 87%
rename from wifi/1.5/default/wifi_legacy_hal_factory.cpp
rename to wifi/1.6/default/wifi_legacy_hal_factory.cpp
index fbaa284..147bf4d 100644
--- a/wifi/1.5/default/wifi_legacy_hal_factory.cpp
+++ b/wifi/1.6/default/wifi_legacy_hal_factory.cpp
@@ -62,22 +62,20 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace legacy_hal {
 
 WifiLegacyHalFactory::WifiLegacyHalFactory(
-    const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
+        const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
     : iface_tool_(iface_tool) {}
 
 std::vector<std::shared_ptr<WifiLegacyHal>> WifiLegacyHalFactory::getHals() {
     if (legacy_hals_.empty()) {
-        if (!initVendorHalDescriptorFromLinked())
-            initVendorHalsDescriptorList();
+        if (!initVendorHalDescriptorFromLinked()) initVendorHalsDescriptorList();
         for (auto& desc : descs_) {
             std::shared_ptr<WifiLegacyHal> hal =
-                std::make_shared<WifiLegacyHal>(iface_tool_, desc.fn,
-                                                desc.primary);
+                    std::make_shared<WifiLegacyHal>(iface_tool_, desc.fn, desc.primary);
             legacy_hals_.push_back(hal);
         }
     }
@@ -99,8 +97,8 @@
 bool WifiLegacyHalFactory::initLinkedHalFunctionTable(wifi_hal_fn* hal_fn) {
     init_wifi_vendor_hal_func_table_t initfn;
 
-    initfn = (init_wifi_vendor_hal_func_table_t)dlsym(
-        RTLD_DEFAULT, "init_wifi_vendor_hal_func_table");
+    initfn = (init_wifi_vendor_hal_func_table_t)dlsym(RTLD_DEFAULT,
+                                                      "init_wifi_vendor_hal_func_table");
     if (!initfn) {
         LOG(INFO) << "no vendor HAL library linked, will try dynamic load";
         return false;
@@ -136,8 +134,7 @@
     xmlChar* value;
     wifi_hal_lib_desc desc;
 
-    LOG(INFO) << "processing vendor HALs descriptions in "
-              << kVendorHalsDescPath;
+    LOG(INFO) << "processing vendor HALs descriptions in " << kVendorHalsDescPath;
     DIR* dirPtr = ::opendir(kVendorHalsDescPath);
     if (dirPtr == NULL) {
         LOG(ERROR) << "failed to open " << kVendorHalsDescPath;
@@ -157,26 +154,23 @@
         fullPath.append(entryPtr->d_name);
         xml = xmlReadFile(fullPath.c_str(), "UTF-8", XML_PARSE_RECOVER);
         if (!xml) {
-            LOG(ERROR) << "failed to parse: " << entryPtr->d_name
-                       << " skipping...";
+            LOG(ERROR) << "failed to parse: " << entryPtr->d_name << " skipping...";
             continue;
         }
         node = xmlDocGetRootElement(xml);
         if (!node) {
-            LOG(ERROR) << "empty config file: " << entryPtr->d_name
-                       << " skipping...";
+            LOG(ERROR) << "empty config file: " << entryPtr->d_name << " skipping...";
             goto skip;
         }
         if (xmlStrcmp(node->name, BAD_CAST "WifiVendorHal")) {
-            LOG(ERROR) << "bad config, root element not WifiVendorHal: "
-                       << entryPtr->d_name << " skipping...";
+            LOG(ERROR) << "bad config, root element not WifiVendorHal: " << entryPtr->d_name
+                       << " skipping...";
             goto skip;
         }
         version = (char*)xmlGetProp(node, BAD_CAST "version");
         if (!version || strtoul(version, NULL, 0) != kVendorHalsDescVersion) {
             LOG(ERROR) << "conf file: " << entryPtr->d_name
-                       << "must have version: " << kVendorHalsDescVersion
-                       << ", skipping...";
+                       << "must have version: " << kVendorHalsDescVersion << ", skipping...";
             goto skip;
         }
         cnode = node->children;
@@ -195,8 +189,8 @@
             cnode = cnode->next;
         }
         if (path.empty()) {
-            LOG(ERROR) << "hal library path not provided in: "
-                       << entryPtr->d_name << ", skipping...";
+            LOG(ERROR) << "hal library path not provided in: " << entryPtr->d_name
+                       << ", skipping...";
             goto skip;
         }
         if (loadVendorHalLib(path, desc)) {
@@ -211,8 +205,7 @@
     ::closedir(dirPtr);
 }
 
-bool WifiLegacyHalFactory::loadVendorHalLib(const std::string& path,
-                                            wifi_hal_lib_desc& desc) {
+bool WifiLegacyHalFactory::loadVendorHalLib(const std::string& path, wifi_hal_lib_desc& desc) {
     void* h = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
     init_wifi_vendor_hal_func_table_t initfn;
     wifi_error res;
@@ -221,8 +214,7 @@
         LOG(ERROR) << "failed to open vendor hal library: " << path;
         return false;
     }
-    initfn = (init_wifi_vendor_hal_func_table_t)dlsym(
-        h, "init_wifi_vendor_hal_func_table");
+    initfn = (init_wifi_vendor_hal_func_table_t)dlsym(h, "init_wifi_vendor_hal_func_table");
     if (!initfn) {
         LOG(ERROR) << "init_wifi_vendor_hal_func_table not found in: " << path;
         goto out_err;
@@ -243,8 +235,7 @@
     // vendor HALs which do not implement early_initialize will return
     // WIFI_ERROR_NOT_SUPPORTED, treat this as success.
     if (res != WIFI_SUCCESS && res != WIFI_ERROR_NOT_SUPPORTED) {
-        LOG(ERROR) << "early initialization failed in: " << path
-                   << " error: " << res;
+        LOG(ERROR) << "early initialization failed in: " << path << " error: " << res;
         goto out_err;
     }
 
@@ -257,7 +248,7 @@
 
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_legacy_hal_factory.h b/wifi/1.6/default/wifi_legacy_hal_factory.h
similarity index 92%
rename from wifi/1.5/default/wifi_legacy_hal_factory.h
rename to wifi/1.6/default/wifi_legacy_hal_factory.h
index e3440fa..9f4423e 100644
--- a/wifi/1.5/default/wifi_legacy_hal_factory.h
+++ b/wifi/1.6/default/wifi_legacy_hal_factory.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 // This is in a separate namespace to prevent typename conflicts between
 // the legacy HAL types and the HIDL interface types.
@@ -33,14 +33,13 @@
  * Class that creates WifiLegacyHal objects for vendor HALs in the system.
  */
 class WifiLegacyHalFactory {
-   public:
-    WifiLegacyHalFactory(
-        const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
+  public:
+    WifiLegacyHalFactory(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
     virtual ~WifiLegacyHalFactory() = default;
 
     std::vector<std::shared_ptr<WifiLegacyHal>> getHals();
 
-   private:
+  private:
     typedef struct {
         wifi_hal_fn fn;
         bool primary;
@@ -59,7 +58,7 @@
 
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp b/wifi/1.6/default/wifi_legacy_hal_stubs.cpp
similarity index 99%
rename from wifi/1.5/default/wifi_legacy_hal_stubs.cpp
rename to wifi/1.6/default/wifi_legacy_hal_stubs.cpp
index dd860d6..e03e1ae 100644
--- a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.6/default/wifi_legacy_hal_stubs.cpp
@@ -20,7 +20,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace legacy_hal {
 template <typename>
@@ -165,7 +165,7 @@
 }
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_legacy_hal_stubs.h b/wifi/1.6/default/wifi_legacy_hal_stubs.h
similarity index 96%
rename from wifi/1.5/default/wifi_legacy_hal_stubs.h
rename to wifi/1.6/default/wifi_legacy_hal_stubs.h
index 480389b..c9a03bf 100644
--- a/wifi/1.5/default/wifi_legacy_hal_stubs.h
+++ b/wifi/1.6/default/wifi_legacy_hal_stubs.h
@@ -22,14 +22,14 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace legacy_hal {
 
 bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn);
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_mode_controller.cpp b/wifi/1.6/default/wifi_mode_controller.cpp
similarity index 90%
rename from wifi/1.5/default/wifi_mode_controller.cpp
rename to wifi/1.6/default/wifi_mode_controller.cpp
index b1db8b3..4b8ac7d 100644
--- a/wifi/1.5/default/wifi_mode_controller.cpp
+++ b/wifi/1.6/default/wifi_mode_controller.cpp
@@ -48,15 +48,14 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace mode_controller {
 
 WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {}
 
 bool WifiModeController::isFirmwareModeChangeNeeded(IfaceType type) {
-    return driver_tool_->IsFirmwareModeChangeNeeded(
-        convertIfaceTypeToFirmwareMode(type));
+    return driver_tool_->IsFirmwareModeChangeNeeded(convertIfaceTypeToFirmwareMode(type));
 }
 
 bool WifiModeController::initialize() {
@@ -68,8 +67,7 @@
 }
 
 bool WifiModeController::changeFirmwareMode(IfaceType type) {
-    if (!driver_tool_->ChangeFirmwareMode(
-            convertIfaceTypeToFirmwareMode(type))) {
+    if (!driver_tool_->ChangeFirmwareMode(convertIfaceTypeToFirmwareMode(type))) {
         LOG(ERROR) << "Failed to change firmware mode";
         return false;
     }
@@ -85,7 +83,7 @@
 }
 }  // namespace mode_controller
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_mode_controller.h b/wifi/1.6/default/wifi_mode_controller.h
similarity index 96%
rename from wifi/1.5/default/wifi_mode_controller.h
rename to wifi/1.6/default/wifi_mode_controller.h
index 2eeca78..fee2b66 100644
--- a/wifi/1.5/default/wifi_mode_controller.h
+++ b/wifi/1.6/default/wifi_mode_controller.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 namespace mode_controller {
 using namespace android::hardware::wifi::V1_0;
@@ -35,7 +35,7 @@
  * required state (essentially a wrapper over DriverTool).
  */
 class WifiModeController {
-   public:
+  public:
     WifiModeController();
     virtual ~WifiModeController() = default;
 
@@ -49,13 +49,13 @@
     // invoked.
     virtual bool deinitialize();
 
-   private:
+  private:
     std::unique_ptr<wifi_hal::DriverTool> driver_tool_;
 };
 
 }  // namespace mode_controller
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.6/default/wifi_nan_iface.cpp b/wifi/1.6/default/wifi_nan_iface.cpp
new file mode 100644
index 0000000..236cb64
--- /dev/null
+++ b/wifi/1.6/default/wifi_nan_iface.cpp
@@ -0,0 +1,905 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include "hidl_return_util.h"
+#include "hidl_struct_util.h"
+#include "wifi_nan_iface.h"
+#include "wifi_status_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_6 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+WifiNanIface::WifiNanIface(const std::string& ifname, bool is_dedicated_iface,
+                           const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+                           const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
+    : ifname_(ifname),
+      is_dedicated_iface_(is_dedicated_iface),
+      legacy_hal_(legacy_hal),
+      iface_util_(iface_util),
+      is_valid_(true) {
+    if (is_dedicated_iface_) {
+        // If using a dedicated iface, set the iface up first.
+        if (!iface_util_.lock()->setUpState(ifname_, true)) {
+            // Fatal failure, invalidate the iface object.
+            invalidate();
+            return;
+        }
+    }
+    // Register all the callbacks here. these should be valid for the lifetime
+    // of the object. Whenever the mode changes legacy HAL will remove
+    // all of these callbacks.
+    legacy_hal::NanCallbackHandlers callback_handlers;
+    android::wp<WifiNanIface> weak_ptr_this(this);
+
+    // Callback for response.
+    callback_handlers.on_notify_response = [weak_ptr_this](legacy_hal::transaction_id id,
+                                                           const legacy_hal::NanResponseMsg& msg) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        WifiNanStatus wifiNanStatus;
+        if (!hidl_struct_util::convertLegacyNanResponseHeaderToHidl(msg, &wifiNanStatus)) {
+            LOG(ERROR) << "Failed to convert nan response header";
+            return;
+        }
+
+        switch (msg.response_type) {
+            case legacy_hal::NAN_RESPONSE_ENABLED: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyEnableResponse(id, wifiNanStatus).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_DISABLED: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyDisableResponse(id, wifiNanStatus).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_PUBLISH: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyStartPublishResponse(id, wifiNanStatus,
+                                                              msg.body.publish_response.publish_id)
+                                 .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_PUBLISH_CANCEL: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyStopPublishResponse(id, wifiNanStatus).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_TRANSMIT_FOLLOWUP: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyTransmitFollowupResponse(id, wifiNanStatus).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_SUBSCRIBE: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyStartSubscribeResponse(
+                                         id, wifiNanStatus,
+                                         msg.body.subscribe_response.subscribe_id)
+                                 .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_SUBSCRIBE_CANCEL: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyStopSubscribeResponse(id, wifiNanStatus).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_CONFIG: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyConfigResponse(id, wifiNanStatus).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_GET_CAPABILITIES: {
+                V1_5::NanCapabilities hidl_struct;
+                if (!hidl_struct_util::convertLegacyNanCapabilitiesResponseToHidl(
+                            msg.body.nan_capabilities, &hidl_struct)) {
+                    LOG(ERROR) << "Failed to convert nan capabilities response";
+                    return;
+                }
+                for (const auto& callback : shared_ptr_this->getEventCallbacks_1_5()) {
+                    if (!callback->notifyCapabilitiesResponse_1_5(id, wifiNanStatus, hidl_struct)
+                                 .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_DP_INTERFACE_CREATE: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyCreateDataInterfaceResponse(id, wifiNanStatus).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_DP_INTERFACE_DELETE: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyDeleteDataInterfaceResponse(id, wifiNanStatus).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_DP_INITIATOR_RESPONSE: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyInitiateDataPathResponse(
+                                         id, wifiNanStatus,
+                                         msg.body.data_request_response.ndp_instance_id)
+                                 .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_DP_RESPONDER_RESPONSE: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyRespondToDataPathIndicationResponse(id, wifiNanStatus)
+                                 .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_DP_END: {
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyTerminateDataPathResponse(id, wifiNanStatus).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_BEACON_SDF_PAYLOAD:
+            /* fall through */
+            case legacy_hal::NAN_RESPONSE_TCA:
+            /* fall through */
+            case legacy_hal::NAN_RESPONSE_STATS:
+            /* fall through */
+            case legacy_hal::NAN_RESPONSE_ERROR:
+            /* fall through */
+            default:
+                LOG(ERROR) << "Unknown or unhandled response type: " << msg.response_type;
+                return;
+        }
+    };
+
+    callback_handlers.on_event_disc_eng_event =
+            [weak_ptr_this](const legacy_hal::NanDiscEngEventInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                NanClusterEventInd hidl_struct;
+                // event types defined identically - hence can be cast
+                hidl_struct.eventType = (NanClusterEventType)msg.event_type;
+                hidl_struct.addr = msg.data.mac_addr.addr;
+
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->eventClusterEvent(hidl_struct).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            };
+
+    callback_handlers.on_event_disabled = [weak_ptr_this](const legacy_hal::NanDisabledInd& msg) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        WifiNanStatus status;
+        hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason),
+                                                 &status);
+
+        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+            if (!callback->eventDisabled(status).isOk()) {
+                LOG(ERROR) << "Failed to invoke the callback";
+            }
+        }
+    };
+
+    callback_handlers.on_event_publish_terminated =
+            [weak_ptr_this](const legacy_hal::NanPublishTerminatedInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                WifiNanStatus status;
+                hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason,
+                                                         sizeof(msg.nan_reason), &status);
+
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->eventPublishTerminated(msg.publish_id, status).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            };
+
+    callback_handlers.on_event_subscribe_terminated =
+            [weak_ptr_this](const legacy_hal::NanSubscribeTerminatedInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                WifiNanStatus status;
+                hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason,
+                                                         sizeof(msg.nan_reason), &status);
+
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->eventSubscribeTerminated(msg.subscribe_id, status).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            };
+
+    callback_handlers.on_event_match = [weak_ptr_this](const legacy_hal::NanMatchInd& msg) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        NanMatchInd hidl_struct;
+        if (!hidl_struct_util::convertLegacyNanMatchIndToHidl(msg, &hidl_struct)) {
+            LOG(ERROR) << "Failed to convert nan capabilities response";
+            return;
+        }
+
+        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+            if (!callback->eventMatch(hidl_struct).isOk()) {
+                LOG(ERROR) << "Failed to invoke the callback";
+            }
+        }
+    };
+
+    callback_handlers.on_event_match_expired = [weak_ptr_this](
+                                                       const legacy_hal::NanMatchExpiredInd& msg) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+            if (!callback->eventMatchExpired(msg.publish_subscribe_id, msg.requestor_instance_id)
+                         .isOk()) {
+                LOG(ERROR) << "Failed to invoke the callback";
+            }
+        }
+    };
+
+    callback_handlers.on_event_followup = [weak_ptr_this](const legacy_hal::NanFollowupInd& msg) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        NanFollowupReceivedInd hidl_struct;
+        if (!hidl_struct_util::convertLegacyNanFollowupIndToHidl(msg, &hidl_struct)) {
+            LOG(ERROR) << "Failed to convert nan capabilities response";
+            return;
+        }
+
+        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+            if (!callback->eventFollowupReceived(hidl_struct).isOk()) {
+                LOG(ERROR) << "Failed to invoke the callback";
+            }
+        }
+    };
+
+    callback_handlers.on_event_transmit_follow_up =
+            [weak_ptr_this](const legacy_hal::NanTransmitFollowupInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                WifiNanStatus status;
+                hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason,
+                                                         sizeof(msg.nan_reason), &status);
+
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->eventTransmitFollowup(msg.id, status).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            };
+
+    callback_handlers.on_event_data_path_request =
+            [weak_ptr_this](const legacy_hal::NanDataPathRequestInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                NanDataPathRequestInd hidl_struct;
+                if (!hidl_struct_util::convertLegacyNanDataPathRequestIndToHidl(msg,
+                                                                                &hidl_struct)) {
+                    LOG(ERROR) << "Failed to convert nan capabilities response";
+                    return;
+                }
+
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->eventDataPathRequest(hidl_struct).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            };
+
+    callback_handlers.on_event_data_path_confirm =
+            [weak_ptr_this](const legacy_hal::NanDataPathConfirmInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                V1_2::NanDataPathConfirmInd hidl_struct;
+                if (!hidl_struct_util::convertLegacyNanDataPathConfirmIndToHidl(msg,
+                                                                                &hidl_struct)) {
+                    LOG(ERROR) << "Failed to convert nan capabilities response";
+                    return;
+                }
+
+                for (const auto& callback : shared_ptr_this->getEventCallbacks_1_2()) {
+                    if (!callback->eventDataPathConfirm_1_2(hidl_struct).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            };
+
+    callback_handlers.on_event_data_path_end =
+            [weak_ptr_this](const legacy_hal::NanDataPathEndInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    for (int i = 0; i < msg.num_ndp_instances; ++i) {
+                        if (!callback->eventDataPathTerminated(msg.ndp_instance_id[i]).isOk()) {
+                            LOG(ERROR) << "Failed to invoke the callback";
+                        }
+                    }
+                }
+            };
+
+    callback_handlers.on_event_beacon_sdf_payload =
+            [weak_ptr_this](const legacy_hal::NanBeaconSdfPayloadInd& /* msg */) {
+                LOG(ERROR) << "on_event_beacon_sdf_payload - should not be called";
+            };
+
+    callback_handlers.on_event_range_request =
+            [weak_ptr_this](const legacy_hal::NanRangeRequestInd& /* msg */) {
+                LOG(ERROR) << "on_event_range_request - should not be called";
+            };
+
+    callback_handlers.on_event_range_report =
+            [weak_ptr_this](const legacy_hal::NanRangeReportInd& /* msg */) {
+                LOG(ERROR) << "on_event_range_report - should not be called";
+            };
+
+    callback_handlers.on_event_schedule_update =
+            [weak_ptr_this](const legacy_hal::NanDataPathScheduleUpdateInd& msg) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                V1_2::NanDataPathScheduleUpdateInd hidl_struct;
+                if (!hidl_struct_util::convertLegacyNanDataPathScheduleUpdateIndToHidl(
+                            msg, &hidl_struct)) {
+                    LOG(ERROR) << "Failed to convert nan capabilities response";
+                    return;
+                }
+
+                for (const auto& callback : shared_ptr_this->getEventCallbacks_1_2()) {
+                    if (!callback->eventDataPathScheduleUpdate(hidl_struct).isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            };
+
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanRegisterCallbackHandlers(ifname_, callback_handlers);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to register nan callbacks. Invalidating object";
+        invalidate();
+    }
+
+    // Register for iface state toggle events.
+    iface_util::IfaceEventHandlers event_handlers = {};
+    event_handlers.on_state_toggle_off_on = [weak_ptr_this](const std::string& /* iface_name */) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        // Tell framework that NAN has been disabled.
+        WifiNanStatus status = {NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
+        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+            if (!callback->eventDisabled(status).isOk()) {
+                LOG(ERROR) << "Failed to invoke the callback";
+            }
+        }
+    };
+    iface_util_.lock()->registerIfaceEventHandlers(ifname_, event_handlers);
+}
+
+void WifiNanIface::invalidate() {
+    if (!isValid()) {
+        return;
+    }
+    // send commands to HAL to actually disable and destroy interfaces
+    legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF);
+    legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0");
+    legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1");
+    iface_util_.lock()->unregisterIfaceEventHandlers(ifname_);
+    legacy_hal_.reset();
+    event_cb_handler_.invalidate();
+    event_cb_handler_1_2_.invalidate();
+    event_cb_handler_1_5_.invalidate();
+    is_valid_ = false;
+    if (is_dedicated_iface_) {
+        // If using a dedicated iface, set the iface down.
+        iface_util_.lock()->setUpState(ifname_, false);
+    }
+}
+
+bool WifiNanIface::isValid() {
+    return is_valid_;
+}
+
+std::string WifiNanIface::getName() {
+    return ifname_;
+}
+
+std::set<sp<V1_0::IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks() {
+    return event_cb_handler_.getCallbacks();
+}
+
+std::set<sp<V1_2::IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks_1_2() {
+    return event_cb_handler_1_2_.getCallbacks();
+}
+
+std::set<sp<V1_5::IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks_1_5() {
+    return event_cb_handler_1_5_.getCallbacks();
+}
+
+Return<void> WifiNanIface::getName(getName_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::getNameInternal, hidl_status_cb);
+}
+
+Return<void> WifiNanIface::getType(getType_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::getTypeInternal, hidl_status_cb);
+}
+
+Return<void> WifiNanIface::registerEventCallback(
+        const sp<V1_0::IWifiNanIfaceEventCallback>& callback,
+        registerEventCallback_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::registerEventCallbackInternal, hidl_status_cb, callback);
+}
+
+Return<void> WifiNanIface::getCapabilitiesRequest(uint16_t cmd_id,
+                                                  getCapabilitiesRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::getCapabilitiesRequestInternal, hidl_status_cb, cmd_id);
+}
+
+Return<void> WifiNanIface::enableRequest(uint16_t cmd_id, const V1_0::NanEnableRequest& msg,
+                                         enableRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::enableRequestInternal, hidl_status_cb, cmd_id, msg);
+}
+
+Return<void> WifiNanIface::configRequest(uint16_t cmd_id, const V1_0::NanConfigRequest& msg,
+                                         configRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::configRequestInternal, hidl_status_cb, cmd_id, msg);
+}
+
+Return<void> WifiNanIface::disableRequest(uint16_t cmd_id, disableRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::disableRequestInternal, hidl_status_cb, cmd_id);
+}
+
+Return<void> WifiNanIface::startPublishRequest(uint16_t cmd_id, const NanPublishRequest& msg,
+                                               startPublishRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::startPublishRequestInternal, hidl_status_cb, cmd_id, msg);
+}
+
+Return<void> WifiNanIface::stopPublishRequest(uint16_t cmd_id, uint8_t sessionId,
+                                              stopPublishRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::stopPublishRequestInternal, hidl_status_cb, cmd_id,
+                           sessionId);
+}
+
+Return<void> WifiNanIface::startSubscribeRequest(uint16_t cmd_id, const NanSubscribeRequest& msg,
+                                                 startSubscribeRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::startSubscribeRequestInternal, hidl_status_cb, cmd_id,
+                           msg);
+}
+
+Return<void> WifiNanIface::stopSubscribeRequest(uint16_t cmd_id, uint8_t sessionId,
+                                                stopSubscribeRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::stopSubscribeRequestInternal, hidl_status_cb, cmd_id,
+                           sessionId);
+}
+
+Return<void> WifiNanIface::transmitFollowupRequest(uint16_t cmd_id,
+                                                   const NanTransmitFollowupRequest& msg,
+                                                   transmitFollowupRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::transmitFollowupRequestInternal, hidl_status_cb, cmd_id,
+                           msg);
+}
+
+Return<void> WifiNanIface::createDataInterfaceRequest(
+        uint16_t cmd_id, const hidl_string& iface_name,
+        createDataInterfaceRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::createDataInterfaceRequestInternal, hidl_status_cb,
+                           cmd_id, iface_name);
+}
+
+Return<void> WifiNanIface::deleteDataInterfaceRequest(
+        uint16_t cmd_id, const hidl_string& iface_name,
+        deleteDataInterfaceRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::deleteDataInterfaceRequestInternal, hidl_status_cb,
+                           cmd_id, iface_name);
+}
+
+Return<void> WifiNanIface::initiateDataPathRequest(uint16_t cmd_id,
+                                                   const NanInitiateDataPathRequest& msg,
+                                                   initiateDataPathRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::initiateDataPathRequestInternal, hidl_status_cb, cmd_id,
+                           msg);
+}
+
+Return<void> WifiNanIface::respondToDataPathIndicationRequest(
+        uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg,
+        respondToDataPathIndicationRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::respondToDataPathIndicationRequestInternal,
+                           hidl_status_cb, cmd_id, msg);
+}
+
+Return<void> WifiNanIface::terminateDataPathRequest(uint16_t cmd_id, uint32_t ndpInstanceId,
+                                                    terminateDataPathRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::terminateDataPathRequestInternal, hidl_status_cb, cmd_id,
+                           ndpInstanceId);
+}
+
+Return<void> WifiNanIface::registerEventCallback_1_2(
+        const sp<V1_2::IWifiNanIfaceEventCallback>& callback,
+        registerEventCallback_1_2_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::registerEventCallback_1_2Internal, hidl_status_cb,
+                           callback);
+}
+
+Return<void> WifiNanIface::enableRequest_1_2(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
+                                             const V1_2::NanConfigRequestSupplemental& msg2,
+                                             enableRequest_1_2_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::enableRequest_1_2Internal, hidl_status_cb, cmd_id, msg1,
+                           msg2);
+}
+
+Return<void> WifiNanIface::configRequest_1_2(uint16_t cmd_id, const V1_0::NanConfigRequest& msg1,
+                                             const V1_2::NanConfigRequestSupplemental& msg2,
+                                             configRequest_1_2_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::configRequest_1_2Internal, hidl_status_cb, cmd_id, msg1,
+                           msg2);
+}
+
+Return<void> WifiNanIface::enableRequest_1_4(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
+                                             const V1_2::NanConfigRequestSupplemental& msg2,
+                                             enableRequest_1_4_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::enableRequest_1_4Internal, hidl_status_cb, cmd_id, msg1,
+                           msg2);
+}
+
+Return<void> WifiNanIface::configRequest_1_4(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
+                                             const V1_2::NanConfigRequestSupplemental& msg2,
+                                             configRequest_1_4_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::configRequest_1_4Internal, hidl_status_cb, cmd_id, msg1,
+                           msg2);
+}
+
+Return<void> WifiNanIface::registerEventCallback_1_5(
+        const sp<V1_5::IWifiNanIfaceEventCallback>& callback,
+        registerEventCallback_1_5_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::registerEventCallback_1_5Internal, hidl_status_cb,
+                           callback);
+}
+
+Return<void> WifiNanIface::enableRequest_1_5(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
+                                             const V1_5::NanConfigRequestSupplemental& msg2,
+                                             enableRequest_1_5_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::enableRequest_1_5Internal, hidl_status_cb, cmd_id, msg1,
+                           msg2);
+}
+
+Return<void> WifiNanIface::configRequest_1_5(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
+                                             const V1_5::NanConfigRequestSupplemental& msg2,
+                                             configRequest_1_5_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::configRequest_1_5Internal, hidl_status_cb, cmd_id, msg1,
+                           msg2);
+}
+
+Return<void> WifiNanIface::getCapabilitiesRequest_1_5(
+        uint16_t cmd_id, getCapabilitiesRequest_1_5_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::getCapabilitiesRequest_1_5Internal, hidl_status_cb,
+                           cmd_id);
+}
+
+std::pair<WifiStatus, std::string> WifiNanIface::getNameInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
+}
+
+std::pair<WifiStatus, IfaceType> WifiNanIface::getTypeInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::NAN};
+}
+
+WifiStatus WifiNanIface::registerEventCallbackInternal(
+        const sp<V1_0::IWifiNanIfaceEventCallback>& callback) {
+    if (!event_cb_handler_.addCallback(callback)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t /* cmd_id */) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiNanIface::enableRequestInternal(uint16_t /* cmd_id */,
+                                               const V1_0::NanEnableRequest& /* msg */) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiNanIface::configRequestInternal(uint16_t /* cmd_id */,
+                                               const V1_0::NanConfigRequest& /* msg */) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiNanIface::disableRequestInternal(uint16_t cmd_id) {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->nanDisableRequest(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::startPublishRequestInternal(uint16_t cmd_id,
+                                                     const NanPublishRequest& msg) {
+    legacy_hal::NanPublishRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanPublishRequestToLegacy(msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanPublishRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId) {
+    legacy_hal::NanPublishCancelRequest legacy_msg;
+    legacy_msg.publish_id = sessionId;
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanPublishCancelRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::startSubscribeRequestInternal(uint16_t cmd_id,
+                                                       const NanSubscribeRequest& msg) {
+    legacy_hal::NanSubscribeRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanSubscribeRequestToLegacy(msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanSubscribeRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::stopSubscribeRequestInternal(uint16_t cmd_id, uint8_t sessionId) {
+    legacy_hal::NanSubscribeCancelRequest legacy_msg;
+    legacy_msg.subscribe_id = sessionId;
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanSubscribeCancelRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::transmitFollowupRequestInternal(uint16_t cmd_id,
+                                                         const NanTransmitFollowupRequest& msg) {
+    legacy_hal::NanTransmitFollowupRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanTransmitFollowupRequestToLegacy(msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanTransmitFollowupRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::createDataInterfaceRequestInternal(uint16_t cmd_id,
+                                                            const std::string& iface_name) {
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanDataInterfaceCreate(ifname_, cmd_id, iface_name);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+WifiStatus WifiNanIface::deleteDataInterfaceRequestInternal(uint16_t cmd_id,
+                                                            const std::string& iface_name) {
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, cmd_id, iface_name);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+WifiStatus WifiNanIface::initiateDataPathRequestInternal(uint16_t cmd_id,
+                                                         const NanInitiateDataPathRequest& msg) {
+    legacy_hal::NanDataPathInitiatorRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanDataPathInitiatorRequestToLegacy(msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanDataRequestInitiator(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+WifiStatus WifiNanIface::respondToDataPathIndicationRequestInternal(
+        uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg) {
+    legacy_hal::NanDataPathIndicationResponse legacy_msg;
+    if (!hidl_struct_util::convertHidlNanDataPathIndicationResponseToLegacy(msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanDataIndicationResponse(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+WifiStatus WifiNanIface::terminateDataPathRequestInternal(uint16_t cmd_id, uint32_t ndpInstanceId) {
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanDataEnd(ifname_, cmd_id, ndpInstanceId);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::registerEventCallback_1_2Internal(
+        const sp<V1_2::IWifiNanIfaceEventCallback>& callback) {
+    sp<V1_0::IWifiNanIfaceEventCallback> callback_1_0 = callback;
+    if (!event_cb_handler_.addCallback(callback_1_0)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    if (!event_cb_handler_1_2_.addCallback(callback)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+WifiStatus WifiNanIface::enableRequest_1_2Internal(
+        uint16_t /* cmd_id */, const V1_0::NanEnableRequest& /* msg1 */,
+        const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiNanIface::configRequest_1_2Internal(
+        uint16_t /* cmd_id */, const V1_0::NanConfigRequest& /* msg1 */,
+        const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiNanIface::enableRequest_1_4Internal(
+        uint16_t /* cmd_id */, const V1_4::NanEnableRequest& /* msg1 */,
+        const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiNanIface::configRequest_1_4Internal(
+        uint16_t /* cmd_id */, const V1_4::NanConfigRequest& /* msg1 */,
+        const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiNanIface::registerEventCallback_1_5Internal(
+        const sp<V1_5::IWifiNanIfaceEventCallback>& callback) {
+    sp<V1_0::IWifiNanIfaceEventCallback> callback_1_0 = callback;
+    if (!event_cb_handler_.addCallback(callback_1_0)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    sp<V1_2::IWifiNanIfaceEventCallback> callback_1_2 = callback;
+    if (!event_cb_handler_1_2_.addCallback(callback_1_2)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    if (!event_cb_handler_1_5_.addCallback(callback)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+WifiStatus WifiNanIface::getCapabilitiesRequest_1_5Internal(uint16_t cmd_id) {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->nanGetCapabilities(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::enableRequest_1_5Internal(uint16_t cmd_id,
+                                                   const V1_4::NanEnableRequest& msg1,
+                                                   const V1_5::NanConfigRequestSupplemental& msg2) {
+    legacy_hal::NanEnableRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanEnableRequest_1_5ToLegacy(msg1, msg2, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::configRequest_1_5Internal(uint16_t cmd_id,
+                                                   const V1_4::NanConfigRequest& msg1,
+                                                   const V1_5::NanConfigRequestSupplemental& msg2) {
+    legacy_hal::NanConfigRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanConfigRequest_1_5ToLegacy(msg1, msg2, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+}  // namespace implementation
+}  // namespace V1_6
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.6/default/wifi_nan_iface.h b/wifi/1.6/default/wifi_nan_iface.h
new file mode 100644
index 0000000..c445afc
--- /dev/null
+++ b/wifi/1.6/default/wifi_nan_iface.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WIFI_NAN_IFACE_H_
+#define WIFI_NAN_IFACE_H_
+
+#include <android-base/macros.h>
+#include <android/hardware/wifi/1.5/IWifiNanIface.h>
+#include <android/hardware/wifi/1.5/IWifiNanIfaceEventCallback.h>
+
+#include "hidl_callback_util.h"
+#include "wifi_iface_util.h"
+#include "wifi_legacy_hal.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_6 {
+namespace implementation {
+using namespace android::hardware::wifi::V1_0;
+using namespace android::hardware::wifi::V1_2;
+
+/**
+ * HIDL interface object used to control a NAN Iface instance.
+ */
+class WifiNanIface : public V1_5::IWifiNanIface {
+  public:
+    WifiNanIface(const std::string& ifname, bool is_dedicated_iface,
+                 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+                 const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
+    // Refer to |WifiChip::invalidate()|.
+    void invalidate();
+    bool isValid();
+    std::string getName();
+
+    // HIDL methods exposed.
+    Return<void> getName(getName_cb hidl_status_cb) override;
+    Return<void> getType(getType_cb hidl_status_cb) override;
+    Return<void> registerEventCallback(const sp<V1_0::IWifiNanIfaceEventCallback>& callback,
+                                       registerEventCallback_cb hidl_status_cb) override;
+    Return<void> getCapabilitiesRequest(uint16_t cmd_id,
+                                        getCapabilitiesRequest_cb hidl_status_cb) override;
+    Return<void> enableRequest(uint16_t cmd_id, const V1_0::NanEnableRequest& msg,
+                               enableRequest_cb hidl_status_cb) override;
+    Return<void> configRequest(uint16_t cmd_id, const V1_0::NanConfigRequest& msg,
+                               configRequest_cb hidl_status_cb) override;
+    Return<void> disableRequest(uint16_t cmd_id, disableRequest_cb hidl_status_cb) override;
+    Return<void> startPublishRequest(uint16_t cmd_id, const NanPublishRequest& msg,
+                                     startPublishRequest_cb hidl_status_cb) override;
+    Return<void> stopPublishRequest(uint16_t cmd_id, uint8_t sessionId,
+                                    stopPublishRequest_cb hidl_status_cb) override;
+    Return<void> startSubscribeRequest(uint16_t cmd_id, const NanSubscribeRequest& msg,
+                                       startSubscribeRequest_cb hidl_status_cb) override;
+    Return<void> stopSubscribeRequest(uint16_t cmd_id, uint8_t sessionId,
+                                      stopSubscribeRequest_cb hidl_status_cb) override;
+    Return<void> transmitFollowupRequest(uint16_t cmd_id, const NanTransmitFollowupRequest& msg,
+                                         transmitFollowupRequest_cb hidl_status_cb) override;
+    Return<void> createDataInterfaceRequest(uint16_t cmd_id, const hidl_string& iface_name,
+                                            createDataInterfaceRequest_cb hidl_status_cb) override;
+    Return<void> deleteDataInterfaceRequest(uint16_t cmd_id, const hidl_string& iface_name,
+                                            deleteDataInterfaceRequest_cb hidl_status_cb) override;
+    Return<void> initiateDataPathRequest(uint16_t cmd_id, const NanInitiateDataPathRequest& msg,
+                                         initiateDataPathRequest_cb hidl_status_cb) override;
+    Return<void> respondToDataPathIndicationRequest(
+            uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg,
+            respondToDataPathIndicationRequest_cb hidl_status_cb) override;
+    Return<void> terminateDataPathRequest(uint16_t cmd_id, uint32_t ndpInstanceId,
+                                          terminateDataPathRequest_cb hidl_status_cb) override;
+
+    Return<void> registerEventCallback_1_2(const sp<V1_2::IWifiNanIfaceEventCallback>& callback,
+                                           registerEventCallback_1_2_cb hidl_status_cb) override;
+    Return<void> enableRequest_1_2(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
+                                   const V1_2::NanConfigRequestSupplemental& msg2,
+                                   enableRequest_1_2_cb hidl_status_cb) override;
+    Return<void> configRequest_1_2(uint16_t cmd_id, const V1_0::NanConfigRequest& msg1,
+                                   const V1_2::NanConfigRequestSupplemental& msg2,
+                                   configRequest_1_2_cb hidl_status_cb) override;
+    Return<void> enableRequest_1_4(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
+                                   const V1_2::NanConfigRequestSupplemental& msg2,
+                                   enableRequest_1_4_cb hidl_status_cb) override;
+    Return<void> configRequest_1_4(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
+                                   const V1_2::NanConfigRequestSupplemental& msg2,
+                                   configRequest_1_4_cb hidl_status_cb) override;
+    Return<void> registerEventCallback_1_5(const sp<V1_5::IWifiNanIfaceEventCallback>& callback,
+                                           registerEventCallback_1_5_cb hidl_status_cb) override;
+    Return<void> enableRequest_1_5(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
+                                   const V1_5::NanConfigRequestSupplemental& msg2,
+                                   enableRequest_1_4_cb hidl_status_cb) override;
+    Return<void> configRequest_1_5(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
+                                   const V1_5::NanConfigRequestSupplemental& msg2,
+                                   configRequest_1_4_cb hidl_status_cb) override;
+    Return<void> getCapabilitiesRequest_1_5(uint16_t cmd_id,
+                                            getCapabilitiesRequest_cb hidl_status_cb) override;
+
+  private:
+    // Corresponding worker functions for the HIDL methods.
+    std::pair<WifiStatus, std::string> getNameInternal();
+    std::pair<WifiStatus, IfaceType> getTypeInternal();
+    WifiStatus registerEventCallbackInternal(const sp<V1_0::IWifiNanIfaceEventCallback>& callback);
+    WifiStatus getCapabilitiesRequestInternal(uint16_t cmd_id);
+    WifiStatus enableRequestInternal(uint16_t cmd_id, const V1_0::NanEnableRequest& msg);
+    WifiStatus configRequestInternal(uint16_t cmd_id, const V1_0::NanConfigRequest& msg);
+    WifiStatus disableRequestInternal(uint16_t cmd_id);
+    WifiStatus startPublishRequestInternal(uint16_t cmd_id, const NanPublishRequest& msg);
+    WifiStatus stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId);
+    WifiStatus startSubscribeRequestInternal(uint16_t cmd_id, const NanSubscribeRequest& msg);
+    WifiStatus stopSubscribeRequestInternal(uint16_t cmd_id, uint8_t sessionId);
+    WifiStatus transmitFollowupRequestInternal(uint16_t cmd_id,
+                                               const NanTransmitFollowupRequest& msg);
+    WifiStatus createDataInterfaceRequestInternal(uint16_t cmd_id, const std::string& iface_name);
+    WifiStatus deleteDataInterfaceRequestInternal(uint16_t cmd_id, const std::string& iface_name);
+    WifiStatus initiateDataPathRequestInternal(uint16_t cmd_id,
+                                               const NanInitiateDataPathRequest& msg);
+    WifiStatus respondToDataPathIndicationRequestInternal(
+            uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg);
+    WifiStatus terminateDataPathRequestInternal(uint16_t cmd_id, uint32_t ndpInstanceId);
+
+    WifiStatus registerEventCallback_1_2Internal(
+            const sp<V1_2::IWifiNanIfaceEventCallback>& callback);
+    WifiStatus enableRequest_1_2Internal(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
+                                         const V1_2::NanConfigRequestSupplemental& msg2);
+    WifiStatus configRequest_1_2Internal(uint16_t cmd_id, const V1_0::NanConfigRequest& msg,
+                                         const V1_2::NanConfigRequestSupplemental& msg2);
+    WifiStatus enableRequest_1_4Internal(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
+                                         const V1_2::NanConfigRequestSupplemental& msg2);
+    WifiStatus configRequest_1_4Internal(uint16_t cmd_id, const V1_4::NanConfigRequest& msg,
+                                         const V1_2::NanConfigRequestSupplemental& msg2);
+    WifiStatus registerEventCallback_1_5Internal(
+            const sp<V1_5::IWifiNanIfaceEventCallback>& callback);
+    WifiStatus enableRequest_1_5Internal(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
+                                         const V1_5::NanConfigRequestSupplemental& msg2);
+    WifiStatus configRequest_1_5Internal(uint16_t cmd_id, const V1_4::NanConfigRequest& msg,
+                                         const V1_5::NanConfigRequestSupplemental& msg2);
+    WifiStatus getCapabilitiesRequest_1_5Internal(uint16_t cmd_id);
+
+    // all 1_0 and descendant callbacks
+    std::set<sp<V1_0::IWifiNanIfaceEventCallback>> getEventCallbacks();
+    // all 1_2 and descendant callbacks
+    std::set<sp<V1_2::IWifiNanIfaceEventCallback>> getEventCallbacks_1_2();
+    // all 1_5 and descendant callbacks
+    std::set<sp<V1_5::IWifiNanIfaceEventCallback>> getEventCallbacks_1_5();
+
+    std::string ifname_;
+    bool is_dedicated_iface_;
+    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
+    bool is_valid_;
+    hidl_callback_util::HidlCallbackHandler<V1_0::IWifiNanIfaceEventCallback> event_cb_handler_;
+    hidl_callback_util::HidlCallbackHandler<V1_2::IWifiNanIfaceEventCallback> event_cb_handler_1_2_;
+    hidl_callback_util::HidlCallbackHandler<V1_5::IWifiNanIfaceEventCallback> event_cb_handler_1_5_;
+
+    DISALLOW_COPY_AND_ASSIGN(WifiNanIface);
+};
+
+}  // namespace implementation
+}  // namespace V1_6
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_NAN_IFACE_H_
diff --git a/wifi/1.5/default/wifi_p2p_iface.cpp b/wifi/1.6/default/wifi_p2p_iface.cpp
similarity index 86%
rename from wifi/1.5/default/wifi_p2p_iface.cpp
rename to wifi/1.6/default/wifi_p2p_iface.cpp
index b8893da..d4b1fca 100644
--- a/wifi/1.5/default/wifi_p2p_iface.cpp
+++ b/wifi/1.6/default/wifi_p2p_iface.cpp
@@ -23,13 +23,12 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 
-WifiP2pIface::WifiP2pIface(
-    const std::string& ifname,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+WifiP2pIface::WifiP2pIface(const std::string& ifname,
+                           const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
     : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {}
 
 void WifiP2pIface::invalidate() {
@@ -37,9 +36,13 @@
     is_valid_ = false;
 }
 
-bool WifiP2pIface::isValid() { return is_valid_; }
+bool WifiP2pIface::isValid() {
+    return is_valid_;
+}
 
-std::string WifiP2pIface::getName() { return ifname_; }
+std::string WifiP2pIface::getName() {
+    return ifname_;
+}
 
 Return<void> WifiP2pIface::getName(getName_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
@@ -60,7 +63,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_p2p_iface.h b/wifi/1.6/default/wifi_p2p_iface.h
similarity index 96%
rename from wifi/1.5/default/wifi_p2p_iface.h
rename to wifi/1.6/default/wifi_p2p_iface.h
index c1adc50..0089443 100644
--- a/wifi/1.5/default/wifi_p2p_iface.h
+++ b/wifi/1.6/default/wifi_p2p_iface.h
@@ -25,7 +25,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 
@@ -33,7 +33,7 @@
  * HIDL interface object used to control a P2P Iface instance.
  */
 class WifiP2pIface : public V1_0::IWifiP2pIface {
-   public:
+  public:
     WifiP2pIface(const std::string& ifname,
                  const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
     // Refer to |WifiChip::invalidate()|.
@@ -45,7 +45,7 @@
     Return<void> getName(getName_cb hidl_status_cb) override;
     Return<void> getType(getType_cb hidl_status_cb) override;
 
-   private:
+  private:
     // Corresponding worker functions for the HIDL methods.
     std::pair<WifiStatus, std::string> getNameInternal();
     std::pair<WifiStatus, IfaceType> getTypeInternal();
@@ -58,7 +58,7 @@
 };
 
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.6/default/wifi_rtt_controller.cpp b/wifi/1.6/default/wifi_rtt_controller.cpp
new file mode 100644
index 0000000..f5e1d5a
--- /dev/null
+++ b/wifi/1.6/default/wifi_rtt_controller.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include "hidl_return_util.h"
+#include "hidl_struct_util.h"
+#include "wifi_rtt_controller.h"
+#include "wifi_status_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_6 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+WifiRttController::WifiRttController(const std::string& iface_name,
+                                     const sp<IWifiIface>& bound_iface,
+                                     const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+    : ifname_(iface_name), bound_iface_(bound_iface), legacy_hal_(legacy_hal), is_valid_(true) {}
+
+void WifiRttController::invalidate() {
+    legacy_hal_.reset();
+    event_callbacks_.clear();
+    is_valid_ = false;
+}
+
+bool WifiRttController::isValid() {
+    return is_valid_;
+}
+
+std::vector<sp<V1_4::IWifiRttControllerEventCallback>> WifiRttController::getEventCallbacks() {
+    return event_callbacks_;
+}
+
+std::string WifiRttController::getIfaceName() {
+    return ifname_;
+}
+
+Return<void> WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::getBoundIfaceInternal, hidl_status_cb);
+}
+
+Return<void> WifiRttController::registerEventCallback(
+        const sp<V1_0::IWifiRttControllerEventCallback>& callback,
+        registerEventCallback_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::registerEventCallbackInternal, hidl_status_cb,
+                           callback);
+}
+
+Return<void> WifiRttController::rangeRequest(uint32_t cmd_id,
+                                             const hidl_vec<V1_0::RttConfig>& rtt_configs,
+                                             rangeRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::rangeRequestInternal, hidl_status_cb, cmd_id,
+                           rtt_configs);
+}
+
+Return<void> WifiRttController::rangeCancel(uint32_t cmd_id,
+                                            const hidl_vec<hidl_array<uint8_t, 6>>& addrs,
+                                            rangeCancel_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::rangeCancelInternal, hidl_status_cb, cmd_id, addrs);
+}
+
+Return<void> WifiRttController::getCapabilities(getCapabilities_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::getCapabilitiesInternal, hidl_status_cb);
+}
+
+Return<void> WifiRttController::setLci(uint32_t cmd_id, const RttLciInformation& lci,
+                                       setLci_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::setLciInternal, hidl_status_cb, cmd_id, lci);
+}
+
+Return<void> WifiRttController::setLcr(uint32_t cmd_id, const RttLcrInformation& lcr,
+                                       setLcr_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::setLcrInternal, hidl_status_cb, cmd_id, lcr);
+}
+
+Return<void> WifiRttController::getResponderInfo(getResponderInfo_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::getResponderInfoInternal, hidl_status_cb);
+}
+
+Return<void> WifiRttController::enableResponder(uint32_t cmd_id,
+                                                const WifiChannelInfo& channel_hint,
+                                                uint32_t max_duration_seconds,
+                                                const V1_0::RttResponder& info,
+                                                enableResponder_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::enableResponderInternal, hidl_status_cb, cmd_id,
+                           channel_hint, max_duration_seconds, info);
+}
+
+Return<void> WifiRttController::disableResponder(uint32_t cmd_id,
+                                                 disableResponder_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::disableResponderInternal, hidl_status_cb, cmd_id);
+}
+
+Return<void> WifiRttController::registerEventCallback_1_4(
+        const sp<V1_4::IWifiRttControllerEventCallback>& callback,
+        registerEventCallback_1_4_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::registerEventCallbackInternal_1_4, hidl_status_cb,
+                           callback);
+}
+
+Return<void> WifiRttController::rangeRequest_1_4(uint32_t cmd_id,
+                                                 const hidl_vec<V1_4::RttConfig>& rtt_configs,
+                                                 rangeRequest_1_4_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::rangeRequestInternal_1_4, hidl_status_cb, cmd_id,
+                           rtt_configs);
+}
+
+Return<void> WifiRttController::getCapabilities_1_4(getCapabilities_1_4_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::getCapabilitiesInternal_1_4, hidl_status_cb);
+}
+
+Return<void> WifiRttController::getResponderInfo_1_4(getResponderInfo_1_4_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::getResponderInfoInternal_1_4, hidl_status_cb);
+}
+
+Return<void> WifiRttController::enableResponder_1_4(uint32_t cmd_id,
+                                                    const WifiChannelInfo& channel_hint,
+                                                    uint32_t max_duration_seconds,
+                                                    const V1_4::RttResponder& info,
+                                                    enableResponder_1_4_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::enableResponderInternal_1_4, hidl_status_cb, cmd_id,
+                           channel_hint, max_duration_seconds, info);
+}
+
+std::pair<WifiStatus, sp<IWifiIface>> WifiRttController::getBoundIfaceInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), bound_iface_};
+}
+
+WifiStatus WifiRttController::registerEventCallbackInternal(
+        const sp<V1_0::IWifiRttControllerEventCallback>& /* callback */) {
+    // Deprecated support for this api
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiRttController::rangeRequestInternal(
+        uint32_t /* cmd_id */, const std::vector<V1_0::RttConfig>& /* rtt_configs */) {
+    // Deprecated support for this api
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiRttController::rangeCancelInternal(
+        uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs) {
+    std::vector<std::array<uint8_t, 6>> legacy_addrs;
+    for (const auto& addr : addrs) {
+        legacy_addrs.push_back(addr);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->cancelRttRangeRequest(ifname_, cmd_id, legacy_addrs);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, V1_0::RttCapabilities> WifiRttController::getCapabilitiesInternal() {
+    // Deprecated support for this api
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
+}
+
+WifiStatus WifiRttController::setLciInternal(uint32_t cmd_id, const RttLciInformation& lci) {
+    legacy_hal::wifi_lci_information legacy_lci;
+    if (!hidl_struct_util::convertHidlRttLciInformationToLegacy(lci, &legacy_lci)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->setRttLci(ifname_, cmd_id, legacy_lci);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiRttController::setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr) {
+    legacy_hal::wifi_lcr_information legacy_lcr;
+    if (!hidl_struct_util::convertHidlRttLcrInformationToLegacy(lcr, &legacy_lcr)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->setRttLcr(ifname_, cmd_id, legacy_lcr);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, V1_0::RttResponder> WifiRttController::getResponderInfoInternal() {
+    // Deprecated support for this api
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
+}
+
+WifiStatus WifiRttController::enableResponderInternal(uint32_t /* cmd_id */,
+                                                      const WifiChannelInfo& /* channel_hint */,
+                                                      uint32_t /* max_duration_seconds */,
+                                                      const V1_0::RttResponder& /* info */) {
+    // Deprecated support for this api
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED)};
+}
+
+WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->disableRttResponder(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiRttController::registerEventCallbackInternal_1_4(
+        const sp<V1_4::IWifiRttControllerEventCallback>& callback) {
+    // TODO(b/31632518): remove the callback when the client is destroyed
+    event_callbacks_.emplace_back(callback);
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+WifiStatus WifiRttController::rangeRequestInternal_1_4(
+        uint32_t cmd_id, const std::vector<V1_4::RttConfig>& rtt_configs) {
+    std::vector<legacy_hal::wifi_rtt_config> legacy_configs;
+    if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy(rtt_configs, &legacy_configs)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    android::wp<WifiRttController> weak_ptr_this(this);
+    const auto& on_results_callback =
+            [weak_ptr_this](legacy_hal::wifi_request_id id,
+                            const std::vector<const legacy_hal::wifi_rtt_result*>& results) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                std::vector<V1_4::RttResult> hidl_results;
+                if (!hidl_struct_util::convertLegacyVectorOfRttResultToHidl(results,
+                                                                            &hidl_results)) {
+                    LOG(ERROR) << "Failed to convert rtt results to HIDL structs";
+                    return;
+                }
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    callback->onResults_1_4(id, hidl_results);
+                }
+            };
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRttRangeRequest(
+            ifname_, cmd_id, legacy_configs, on_results_callback);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, V1_4::RttCapabilities> WifiRttController::getCapabilitiesInternal_1_4() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::wifi_rtt_capabilities legacy_caps;
+    std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRttCapabilities(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    V1_4::RttCapabilities hidl_caps;
+    if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps, &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
+}
+
+std::pair<WifiStatus, V1_4::RttResponder> WifiRttController::getResponderInfoInternal_1_4() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::wifi_rtt_responder legacy_responder;
+    std::tie(legacy_status, legacy_responder) = legacy_hal_.lock()->getRttResponderInfo(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    V1_4::RttResponder hidl_responder;
+    if (!hidl_struct_util::convertLegacyRttResponderToHidl(legacy_responder, &hidl_responder)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_responder};
+}
+
+WifiStatus WifiRttController::enableResponderInternal_1_4(uint32_t cmd_id,
+                                                          const WifiChannelInfo& channel_hint,
+                                                          uint32_t max_duration_seconds,
+                                                          const V1_4::RttResponder& info) {
+    legacy_hal::wifi_channel_info legacy_channel_info;
+    if (!hidl_struct_util::convertHidlWifiChannelInfoToLegacy(channel_hint, &legacy_channel_info)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_rtt_responder legacy_responder;
+    if (!hidl_struct_util::convertHidlRttResponderToLegacy(info, &legacy_responder)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableRttResponder(
+            ifname_, cmd_id, legacy_channel_info, max_duration_seconds, legacy_responder);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+}  // namespace implementation
+}  // namespace V1_6
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.6/default/wifi_rtt_controller.h b/wifi/1.6/default/wifi_rtt_controller.h
new file mode 100644
index 0000000..b4a2116
--- /dev/null
+++ b/wifi/1.6/default/wifi_rtt_controller.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WIFI_RTT_CONTROLLER_H_
+#define WIFI_RTT_CONTROLLER_H_
+
+#include <android-base/macros.h>
+#include <android/hardware/wifi/1.0/IWifiIface.h>
+#include <android/hardware/wifi/1.4/IWifiRttController.h>
+#include <android/hardware/wifi/1.4/IWifiRttControllerEventCallback.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_6 {
+namespace implementation {
+
+/**
+ * HIDL interface object used to control all RTT operations.
+ */
+class WifiRttController : public V1_4::IWifiRttController {
+  public:
+    WifiRttController(const std::string& iface_name, const sp<IWifiIface>& bound_iface,
+                      const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+    // Refer to |WifiChip::invalidate()|.
+    void invalidate();
+    bool isValid();
+    std::vector<sp<V1_4::IWifiRttControllerEventCallback>> getEventCallbacks();
+    std::string getIfaceName();
+
+    // HIDL methods exposed.
+    Return<void> getBoundIface(getBoundIface_cb hidl_status_cb) override;
+    Return<void> registerEventCallback(const sp<V1_0::IWifiRttControllerEventCallback>& callback,
+                                       registerEventCallback_cb hidl_status_cb) override;
+    Return<void> rangeRequest(uint32_t cmd_id, const hidl_vec<V1_0::RttConfig>& rtt_configs,
+                              rangeRequest_cb hidl_status_cb) override;
+    Return<void> rangeCancel(uint32_t cmd_id, const hidl_vec<hidl_array<uint8_t, 6>>& addrs,
+                             rangeCancel_cb hidl_status_cb) override;
+    Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
+    Return<void> setLci(uint32_t cmd_id, const RttLciInformation& lci,
+                        setLci_cb hidl_status_cb) override;
+    Return<void> setLcr(uint32_t cmd_id, const RttLcrInformation& lcr,
+                        setLcr_cb hidl_status_cb) override;
+    Return<void> getResponderInfo(getResponderInfo_cb hidl_status_cb) override;
+    Return<void> enableResponder(uint32_t cmd_id, const WifiChannelInfo& channel_hint,
+                                 uint32_t max_duration_seconds, const V1_0::RttResponder& info,
+                                 enableResponder_cb hidl_status_cb) override;
+    Return<void> disableResponder(uint32_t cmd_id, disableResponder_cb hidl_status_cb) override;
+    Return<void> registerEventCallback_1_4(
+            const sp<V1_4::IWifiRttControllerEventCallback>& callback,
+            registerEventCallback_1_4_cb hidl_status_cb) override;
+    Return<void> rangeRequest_1_4(uint32_t cmd_id, const hidl_vec<V1_4::RttConfig>& rtt_configs,
+                                  rangeRequest_1_4_cb hidl_status_cb) override;
+    Return<void> getCapabilities_1_4(getCapabilities_1_4_cb hidl_status_cb) override;
+    Return<void> getResponderInfo_1_4(getResponderInfo_1_4_cb hidl_status_cb) override;
+    Return<void> enableResponder_1_4(uint32_t cmd_id, const WifiChannelInfo& channel_hint,
+                                     uint32_t max_duration_seconds, const V1_4::RttResponder& info,
+                                     enableResponder_1_4_cb hidl_status_cb) override;
+
+  private:
+    // Corresponding worker functions for the HIDL methods.
+    std::pair<WifiStatus, sp<IWifiIface>> getBoundIfaceInternal();
+    WifiStatus registerEventCallbackInternal(
+            const sp<V1_0::IWifiRttControllerEventCallback>& callback);
+    WifiStatus rangeRequestInternal(uint32_t cmd_id,
+                                    const std::vector<V1_0::RttConfig>& rtt_configs);
+    WifiStatus rangeCancelInternal(uint32_t cmd_id,
+                                   const std::vector<hidl_array<uint8_t, 6>>& addrs);
+    std::pair<WifiStatus, V1_0::RttCapabilities> getCapabilitiesInternal();
+    WifiStatus setLciInternal(uint32_t cmd_id, const RttLciInformation& lci);
+    WifiStatus setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr);
+    std::pair<WifiStatus, V1_0::RttResponder> getResponderInfoInternal();
+    WifiStatus enableResponderInternal(uint32_t cmd_id, const WifiChannelInfo& channel_hint,
+                                       uint32_t max_duration_seconds,
+                                       const V1_0::RttResponder& info);
+    WifiStatus disableResponderInternal(uint32_t cmd_id);
+    WifiStatus registerEventCallbackInternal_1_4(
+            const sp<V1_4::IWifiRttControllerEventCallback>& callback);
+    WifiStatus rangeRequestInternal_1_4(uint32_t cmd_id,
+                                        const std::vector<V1_4::RttConfig>& rtt_configs);
+    std::pair<WifiStatus, V1_4::RttCapabilities> getCapabilitiesInternal_1_4();
+    std::pair<WifiStatus, V1_4::RttResponder> getResponderInfoInternal_1_4();
+    WifiStatus enableResponderInternal_1_4(uint32_t cmd_id, const WifiChannelInfo& channel_hint,
+                                           uint32_t max_duration_seconds,
+                                           const V1_4::RttResponder& info);
+
+    std::string ifname_;
+    sp<IWifiIface> bound_iface_;
+    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    std::vector<sp<V1_4::IWifiRttControllerEventCallback>> event_callbacks_;
+    bool is_valid_;
+
+    DISALLOW_COPY_AND_ASSIGN(WifiRttController);
+};
+
+}  // namespace implementation
+}  // namespace V1_6
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_RTT_CONTROLLER_H_
diff --git a/wifi/1.6/default/wifi_sta_iface.cpp b/wifi/1.6/default/wifi_sta_iface.cpp
new file mode 100644
index 0000000..f852d36
--- /dev/null
+++ b/wifi/1.6/default/wifi_sta_iface.cpp
@@ -0,0 +1,583 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include "hidl_return_util.h"
+#include "hidl_struct_util.h"
+#include "wifi_sta_iface.h"
+#include "wifi_status_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_6 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+WifiStaIface::WifiStaIface(const std::string& ifname,
+                           const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+                           const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
+    : ifname_(ifname), legacy_hal_(legacy_hal), iface_util_(iface_util), is_valid_(true) {
+    // Turn on DFS channel usage for STA iface.
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setDfsFlag(ifname_, true);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to set DFS flag; DFS channels may be unavailable.";
+    }
+}
+
+void WifiStaIface::invalidate() {
+    legacy_hal_.reset();
+    event_cb_handler_.invalidate();
+    is_valid_ = false;
+}
+
+bool WifiStaIface::isValid() {
+    return is_valid_;
+}
+
+std::string WifiStaIface::getName() {
+    return ifname_;
+}
+
+std::set<sp<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() {
+    return event_cb_handler_.getCallbacks();
+}
+
+Return<void> WifiStaIface::getName(getName_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getNameInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getType(getType_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getTypeInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::registerEventCallback(const sp<IWifiStaIfaceEventCallback>& callback,
+                                                 registerEventCallback_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::registerEventCallbackInternal, hidl_status_cb, callback);
+}
+
+Return<void> WifiStaIface::getCapabilities(getCapabilities_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getCapabilitiesInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getApfPacketFilterCapabilities(
+        getApfPacketFilterCapabilities_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getApfPacketFilterCapabilitiesInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::installApfPacketFilter(uint32_t cmd_id, const hidl_vec<uint8_t>& program,
+                                                  installApfPacketFilter_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::installApfPacketFilterInternal, hidl_status_cb, cmd_id,
+                           program);
+}
+
+Return<void> WifiStaIface::readApfPacketFilterData(readApfPacketFilterData_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::readApfPacketFilterDataInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getBackgroundScanCapabilities(
+        getBackgroundScanCapabilities_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getBackgroundScanCapabilitiesInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getValidFrequenciesForBand(
+        V1_0::WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getValidFrequenciesForBandInternal, hidl_status_cb, band);
+}
+
+Return<void> WifiStaIface::startBackgroundScan(uint32_t cmd_id,
+                                               const StaBackgroundScanParameters& params,
+                                               startBackgroundScan_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::startBackgroundScanInternal, hidl_status_cb, cmd_id,
+                           params);
+}
+
+Return<void> WifiStaIface::stopBackgroundScan(uint32_t cmd_id,
+                                              stopBackgroundScan_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::stopBackgroundScanInternal, hidl_status_cb, cmd_id);
+}
+
+Return<void> WifiStaIface::enableLinkLayerStatsCollection(
+        bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::enableLinkLayerStatsCollectionInternal, hidl_status_cb,
+                           debug);
+}
+
+Return<void> WifiStaIface::disableLinkLayerStatsCollection(
+        disableLinkLayerStatsCollection_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::disableLinkLayerStatsCollectionInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getLinkLayerStats(getLinkLayerStats_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getLinkLayerStatsInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getLinkLayerStats_1_3(getLinkLayerStats_1_3_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getLinkLayerStatsInternal_1_3, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getLinkLayerStats_1_5(getLinkLayerStats_1_5_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getLinkLayerStatsInternal_1_5, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::startRssiMonitoring(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
+                                               startRssiMonitoring_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::startRssiMonitoringInternal, hidl_status_cb, cmd_id,
+                           max_rssi, min_rssi);
+}
+
+Return<void> WifiStaIface::stopRssiMonitoring(uint32_t cmd_id,
+                                              stopRssiMonitoring_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::stopRssiMonitoringInternal, hidl_status_cb, cmd_id);
+}
+
+Return<void> WifiStaIface::getRoamingCapabilities(getRoamingCapabilities_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getRoamingCapabilitiesInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::configureRoaming(const StaRoamingConfig& config,
+                                            configureRoaming_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::configureRoamingInternal, hidl_status_cb, config);
+}
+
+Return<void> WifiStaIface::setRoamingState(StaRoamingState state,
+                                           setRoamingState_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::setRoamingStateInternal, hidl_status_cb, state);
+}
+
+Return<void> WifiStaIface::enableNdOffload(bool enable, enableNdOffload_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::enableNdOffloadInternal, hidl_status_cb, enable);
+}
+
+Return<void> WifiStaIface::startSendingKeepAlivePackets(
+        uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data, uint16_t ether_type,
+        const hidl_array<uint8_t, 6>& src_address, const hidl_array<uint8_t, 6>& dst_address,
+        uint32_t period_in_ms, startSendingKeepAlivePackets_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::startSendingKeepAlivePacketsInternal, hidl_status_cb,
+                           cmd_id, ip_packet_data, ether_type, src_address, dst_address,
+                           period_in_ms);
+}
+
+Return<void> WifiStaIface::stopSendingKeepAlivePackets(
+        uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::stopSendingKeepAlivePacketsInternal, hidl_status_cb,
+                           cmd_id);
+}
+
+Return<void> WifiStaIface::setScanningMacOui(const hidl_array<uint8_t, 3>& oui,
+                                             setScanningMacOui_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::setScanningMacOuiInternal, hidl_status_cb, oui);
+}
+
+Return<void> WifiStaIface::startDebugPacketFateMonitoring(
+        startDebugPacketFateMonitoring_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::startDebugPacketFateMonitoringInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getDebugTxPacketFates(getDebugTxPacketFates_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getDebugTxPacketFatesInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getDebugRxPacketFates(getDebugRxPacketFates_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getDebugRxPacketFatesInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::setMacAddress(const hidl_array<uint8_t, 6>& mac,
+                                         setMacAddress_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::setMacAddressInternal, hidl_status_cb, mac);
+}
+
+Return<void> WifiStaIface::getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getFactoryMacAddressInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::setScanMode(bool enable, setScanMode_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::setScanModeInternal, hidl_status_cb, enable);
+}
+
+std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
+}
+
+std::pair<WifiStatus, IfaceType> WifiStaIface::getTypeInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::STA};
+}
+
+WifiStatus WifiStaIface::registerEventCallbackInternal(
+        const sp<IWifiStaIfaceEventCallback>& callback) {
+    if (!event_cb_handler_.addCallback(callback)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    uint64_t legacy_feature_set;
+    std::tie(legacy_status, legacy_feature_set) =
+            legacy_hal_.lock()->getSupportedFeatureSet(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), 0};
+    }
+    uint32_t legacy_logger_feature_set;
+    std::tie(legacy_status, legacy_logger_feature_set) =
+            legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        // some devices don't support querying logger feature set
+        legacy_logger_feature_set = 0;
+    }
+    uint32_t hidl_caps;
+    if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities(
+                legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
+}
+
+std::pair<WifiStatus, StaApfPacketFilterCapabilities>
+WifiStaIface::getApfPacketFilterCapabilitiesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::PacketFilterCapabilities legacy_caps;
+    std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getPacketFilterCapabilities(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    StaApfPacketFilterCapabilities hidl_caps;
+    if (!hidl_struct_util::convertLegacyApfCapabilitiesToHidl(legacy_caps, &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
+}
+
+WifiStatus WifiStaIface::installApfPacketFilterInternal(uint32_t /* cmd_id */,
+                                                        const std::vector<uint8_t>& program) {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setPacketFilter(ifname_, program);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, std::vector<uint8_t>> WifiStaIface::readApfPacketFilterDataInternal() {
+    const std::pair<legacy_hal::wifi_error, std::vector<uint8_t>> legacy_status_and_data =
+            legacy_hal_.lock()->readApfPacketFilterData(ifname_);
+    return {createWifiStatusFromLegacyError(legacy_status_and_data.first),
+            std::move(legacy_status_and_data.second)};
+}
+
+std::pair<WifiStatus, StaBackgroundScanCapabilities>
+WifiStaIface::getBackgroundScanCapabilitiesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::wifi_gscan_capabilities legacy_caps;
+    std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getGscanCapabilities(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    StaBackgroundScanCapabilities hidl_caps;
+    if (!hidl_struct_util::convertLegacyGscanCapabilitiesToHidl(legacy_caps, &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
+}
+
+std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
+WifiStaIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) {
+    static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch");
+    legacy_hal::wifi_error legacy_status;
+    std::vector<uint32_t> valid_frequencies;
+    std::tie(legacy_status, valid_frequencies) = legacy_hal_.lock()->getValidFrequenciesForBand(
+            ifname_, hidl_struct_util::convertHidlWifiBandToLegacy(band));
+    return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
+}
+
+WifiStatus WifiStaIface::startBackgroundScanInternal(uint32_t cmd_id,
+                                                     const StaBackgroundScanParameters& params) {
+    legacy_hal::wifi_scan_cmd_params legacy_params;
+    if (!hidl_struct_util::convertHidlGscanParamsToLegacy(params, &legacy_params)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    android::wp<WifiStaIface> weak_ptr_this(this);
+    const auto& on_failure_callback = [weak_ptr_this](legacy_hal::wifi_request_id id) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+            if (!callback->onBackgroundScanFailure(id).isOk()) {
+                LOG(ERROR) << "Failed to invoke onBackgroundScanFailure callback";
+            }
+        }
+    };
+    const auto& on_results_callback =
+            [weak_ptr_this](legacy_hal::wifi_request_id id,
+                            const std::vector<legacy_hal::wifi_cached_scan_results>& results) {
+                const auto shared_ptr_this = weak_ptr_this.promote();
+                if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                    LOG(ERROR) << "Callback invoked on an invalid object";
+                    return;
+                }
+                std::vector<StaScanData> hidl_scan_datas;
+                if (!hidl_struct_util::convertLegacyVectorOfCachedGscanResultsToHidl(
+                            results, &hidl_scan_datas)) {
+                    LOG(ERROR) << "Failed to convert scan results to HIDL structs";
+                    return;
+                }
+                for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->onBackgroundScanResults(id, hidl_scan_datas).isOk()) {
+                        LOG(ERROR) << "Failed to invoke onBackgroundScanResults callback";
+                    }
+                }
+            };
+    const auto& on_full_result_callback = [weak_ptr_this](
+                                                  legacy_hal::wifi_request_id id,
+                                                  const legacy_hal::wifi_scan_result* result,
+                                                  uint32_t buckets_scanned) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        StaScanResult hidl_scan_result;
+        if (!hidl_struct_util::convertLegacyGscanResultToHidl(*result, true, &hidl_scan_result)) {
+            LOG(ERROR) << "Failed to convert full scan results to HIDL structs";
+            return;
+        }
+        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+            if (!callback->onBackgroundFullScanResult(id, buckets_scanned, hidl_scan_result)
+                         .isOk()) {
+                LOG(ERROR) << "Failed to invoke onBackgroundFullScanResult callback";
+            }
+        }
+    };
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->startGscan(ifname_, cmd_id, legacy_params, on_failure_callback,
+                                           on_results_callback, on_full_result_callback);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::stopBackgroundScanInternal(uint32_t cmd_id) {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stopGscan(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableLinkLayerStats(ifname_, debug);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->disableLinkLayerStats(ifname_);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, V1_0::StaLinkLayerStats> WifiStaIface::getLinkLayerStatsInternal() {
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
+}
+
+std::pair<WifiStatus, V1_3::StaLinkLayerStats> WifiStaIface::getLinkLayerStatsInternal_1_3() {
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
+}
+
+std::pair<WifiStatus, V1_5::StaLinkLayerStats> WifiStaIface::getLinkLayerStatsInternal_1_5() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::LinkLayerStats legacy_stats;
+    std::tie(legacy_status, legacy_stats) = legacy_hal_.lock()->getLinkLayerStats(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    V1_5::StaLinkLayerStats hidl_stats;
+    if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, &hidl_stats)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
+}
+
+WifiStatus WifiStaIface::startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi,
+                                                     int32_t min_rssi) {
+    android::wp<WifiStaIface> weak_ptr_this(this);
+    const auto& on_threshold_breached_callback = [weak_ptr_this](legacy_hal::wifi_request_id id,
+                                                                 std::array<uint8_t, 6> bssid,
+                                                                 int8_t rssi) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+            if (!callback->onRssiThresholdBreached(id, bssid, rssi).isOk()) {
+                LOG(ERROR) << "Failed to invoke onRssiThresholdBreached callback";
+            }
+        }
+    };
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRssiMonitoring(
+            ifname_, cmd_id, max_rssi, min_rssi, on_threshold_breached_callback);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::stopRssiMonitoringInternal(uint32_t cmd_id) {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stopRssiMonitoring(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, StaRoamingCapabilities> WifiStaIface::getRoamingCapabilitiesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::wifi_roaming_capabilities legacy_caps;
+    std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRoamingCapabilities(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    StaRoamingCapabilities hidl_caps;
+    if (!hidl_struct_util::convertLegacyRoamingCapabilitiesToHidl(legacy_caps, &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
+}
+
+WifiStatus WifiStaIface::configureRoamingInternal(const StaRoamingConfig& config) {
+    legacy_hal::wifi_roaming_config legacy_config;
+    if (!hidl_struct_util::convertHidlRoamingConfigToLegacy(config, &legacy_config)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->configureRoaming(ifname_, legacy_config);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::setRoamingStateInternal(StaRoamingState state) {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableFirmwareRoaming(
+            ifname_, hidl_struct_util::convertHidlRoamingStateToLegacy(state));
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->configureNdOffload(ifname_, enable);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal(
+        uint32_t cmd_id, const std::vector<uint8_t>& ip_packet_data, uint16_t ether_type,
+        const std::array<uint8_t, 6>& src_address, const std::array<uint8_t, 6>& dst_address,
+        uint32_t period_in_ms) {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startSendingOffloadedPacket(
+            ifname_, cmd_id, ether_type, ip_packet_data, src_address, dst_address, period_in_ms);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::stopSendingKeepAlivePacketsInternal(uint32_t cmd_id) {
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->stopSendingOffloadedPacket(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::setScanningMacOuiInternal(const std::array<uint8_t, 3>& /* oui */) {
+    // deprecated.
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startPktFateMonitoring(ifname_);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
+WifiStaIface::getDebugTxPacketFatesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    std::vector<legacy_hal::wifi_tx_report> legacy_fates;
+    std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getTxPktFates(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    std::vector<WifiDebugTxPacketFateReport> hidl_fates;
+    if (!hidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToHidl(legacy_fates,
+                                                                        &hidl_fates)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
+}
+
+std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
+WifiStaIface::getDebugRxPacketFatesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    std::vector<legacy_hal::wifi_rx_report> legacy_fates;
+    std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getRxPktFates(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    std::vector<WifiDebugRxPacketFateReport> hidl_fates;
+    if (!hidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToHidl(legacy_fates,
+                                                                        &hidl_fates)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
+}
+
+WifiStatus WifiStaIface::setMacAddressInternal(const std::array<uint8_t, 6>& mac) {
+    bool status = iface_util_.lock()->setMacAddress(ifname_, mac);
+    if (!status) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+std::pair<WifiStatus, std::array<uint8_t, 6>> WifiStaIface::getFactoryMacAddressInternal() {
+    std::array<uint8_t, 6> mac = iface_util_.lock()->getFactoryMacAddress(ifname_);
+    if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
+}
+
+WifiStatus WifiStaIface::setScanModeInternal(bool enable) {
+    // OEM's need to implement this on their devices if needed.
+    LOG(WARNING) << "setScanModeInternal(" << enable << ") not supported";
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+}  // namespace implementation
+}  // namespace V1_6
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.6/default/wifi_sta_iface.h b/wifi/1.6/default/wifi_sta_iface.h
new file mode 100644
index 0000000..37358a5
--- /dev/null
+++ b/wifi/1.6/default/wifi_sta_iface.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WIFI_STA_IFACE_H_
+#define WIFI_STA_IFACE_H_
+
+#include <android-base/macros.h>
+#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
+#include <android/hardware/wifi/1.5/IWifiStaIface.h>
+
+#include "hidl_callback_util.h"
+#include "wifi_iface_util.h"
+#include "wifi_legacy_hal.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_6 {
+namespace implementation {
+using namespace android::hardware::wifi::V1_0;
+
+/**
+ * HIDL interface object used to control a STA Iface instance.
+ */
+class WifiStaIface : public V1_5::IWifiStaIface {
+  public:
+    WifiStaIface(const std::string& ifname,
+                 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+                 const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
+    // Refer to |WifiChip::invalidate()|.
+    void invalidate();
+    bool isValid();
+    std::set<sp<IWifiStaIfaceEventCallback>> getEventCallbacks();
+    std::string getName();
+
+    // HIDL methods exposed.
+    Return<void> getName(getName_cb hidl_status_cb) override;
+    Return<void> getType(getType_cb hidl_status_cb) override;
+    Return<void> registerEventCallback(const sp<IWifiStaIfaceEventCallback>& callback,
+                                       registerEventCallback_cb hidl_status_cb) override;
+    Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
+    Return<void> getApfPacketFilterCapabilities(
+            getApfPacketFilterCapabilities_cb hidl_status_cb) override;
+    Return<void> installApfPacketFilter(uint32_t cmd_id, const hidl_vec<uint8_t>& program,
+                                        installApfPacketFilter_cb hidl_status_cb) override;
+    Return<void> readApfPacketFilterData(readApfPacketFilterData_cb hidl_status_cb) override;
+    Return<void> getBackgroundScanCapabilities(
+            getBackgroundScanCapabilities_cb hidl_status_cb) override;
+    Return<void> getValidFrequenciesForBand(V1_0::WifiBand band,
+                                            getValidFrequenciesForBand_cb hidl_status_cb) override;
+    Return<void> startBackgroundScan(uint32_t cmd_id, const StaBackgroundScanParameters& params,
+                                     startBackgroundScan_cb hidl_status_cb) override;
+    Return<void> stopBackgroundScan(uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) override;
+    Return<void> enableLinkLayerStatsCollection(
+            bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) override;
+    Return<void> disableLinkLayerStatsCollection(
+            disableLinkLayerStatsCollection_cb hidl_status_cb) override;
+    Return<void> getLinkLayerStats(getLinkLayerStats_cb hidl_status_cb) override;
+    Return<void> getLinkLayerStats_1_3(getLinkLayerStats_1_3_cb hidl_status_cb) override;
+    Return<void> getLinkLayerStats_1_5(getLinkLayerStats_1_5_cb hidl_status_cb) override;
+    Return<void> startRssiMonitoring(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
+                                     startRssiMonitoring_cb hidl_status_cb) override;
+    Return<void> stopRssiMonitoring(uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) override;
+    Return<void> getRoamingCapabilities(getRoamingCapabilities_cb hidl_status_cb) override;
+    Return<void> configureRoaming(const StaRoamingConfig& config,
+                                  configureRoaming_cb hidl_status_cb) override;
+    Return<void> setRoamingState(StaRoamingState state, setRoamingState_cb hidl_status_cb) override;
+    Return<void> enableNdOffload(bool enable, enableNdOffload_cb hidl_status_cb) override;
+    Return<void> startSendingKeepAlivePackets(
+            uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data, uint16_t ether_type,
+            const hidl_array<uint8_t, 6>& src_address, const hidl_array<uint8_t, 6>& dst_address,
+            uint32_t period_in_ms, startSendingKeepAlivePackets_cb hidl_status_cb) override;
+    Return<void> stopSendingKeepAlivePackets(
+            uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) override;
+    Return<void> setScanningMacOui(const hidl_array<uint8_t, 3>& oui,
+                                   setScanningMacOui_cb hidl_status_cb) override;
+    Return<void> startDebugPacketFateMonitoring(
+            startDebugPacketFateMonitoring_cb hidl_status_cb) override;
+    Return<void> getDebugTxPacketFates(getDebugTxPacketFates_cb hidl_status_cb) override;
+    Return<void> getDebugRxPacketFates(getDebugRxPacketFates_cb hidl_status_cb) override;
+    Return<void> setMacAddress(const hidl_array<uint8_t, 6>& mac,
+                               setMacAddress_cb hidl_status_cb) override;
+    Return<void> getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) override;
+    Return<void> setScanMode(bool enable, setScanMode_cb hidl_status_cb) override;
+
+  private:
+    // Corresponding worker functions for the HIDL methods.
+    std::pair<WifiStatus, std::string> getNameInternal();
+    std::pair<WifiStatus, IfaceType> getTypeInternal();
+    WifiStatus registerEventCallbackInternal(const sp<IWifiStaIfaceEventCallback>& callback);
+    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
+    std::pair<WifiStatus, StaApfPacketFilterCapabilities> getApfPacketFilterCapabilitiesInternal();
+    WifiStatus installApfPacketFilterInternal(uint32_t cmd_id, const std::vector<uint8_t>& program);
+    std::pair<WifiStatus, std::vector<uint8_t>> readApfPacketFilterDataInternal();
+    std::pair<WifiStatus, StaBackgroundScanCapabilities> getBackgroundScanCapabilitiesInternal();
+    std::pair<WifiStatus, std::vector<WifiChannelInMhz>> getValidFrequenciesForBandInternal(
+            V1_0::WifiBand band);
+    WifiStatus startBackgroundScanInternal(uint32_t cmd_id,
+                                           const StaBackgroundScanParameters& params);
+    WifiStatus stopBackgroundScanInternal(uint32_t cmd_id);
+    WifiStatus enableLinkLayerStatsCollectionInternal(bool debug);
+    WifiStatus disableLinkLayerStatsCollectionInternal();
+    std::pair<WifiStatus, V1_0::StaLinkLayerStats> getLinkLayerStatsInternal();
+    std::pair<WifiStatus, V1_3::StaLinkLayerStats> getLinkLayerStatsInternal_1_3();
+    std::pair<WifiStatus, V1_5::StaLinkLayerStats> getLinkLayerStatsInternal_1_5();
+    WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi);
+    WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id);
+    std::pair<WifiStatus, StaRoamingCapabilities> getRoamingCapabilitiesInternal();
+    WifiStatus configureRoamingInternal(const StaRoamingConfig& config);
+    WifiStatus setRoamingStateInternal(StaRoamingState state);
+    WifiStatus enableNdOffloadInternal(bool enable);
+    WifiStatus startSendingKeepAlivePacketsInternal(uint32_t cmd_id,
+                                                    const std::vector<uint8_t>& ip_packet_data,
+                                                    uint16_t ether_type,
+                                                    const std::array<uint8_t, 6>& src_address,
+                                                    const std::array<uint8_t, 6>& dst_address,
+                                                    uint32_t period_in_ms);
+    WifiStatus stopSendingKeepAlivePacketsInternal(uint32_t cmd_id);
+    WifiStatus setScanningMacOuiInternal(const std::array<uint8_t, 3>& oui);
+    WifiStatus startDebugPacketFateMonitoringInternal();
+    std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>> getDebugTxPacketFatesInternal();
+    std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>> getDebugRxPacketFatesInternal();
+    WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
+    std::pair<WifiStatus, std::array<uint8_t, 6>> getFactoryMacAddressInternal();
+    WifiStatus setScanModeInternal(bool enable);
+
+    std::string ifname_;
+    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
+    bool is_valid_;
+    hidl_callback_util::HidlCallbackHandler<IWifiStaIfaceEventCallback> event_cb_handler_;
+
+    DISALLOW_COPY_AND_ASSIGN(WifiStaIface);
+};
+
+}  // namespace implementation
+}  // namespace V1_6
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_STA_IFACE_H_
diff --git a/wifi/1.5/default/wifi_status_util.cpp b/wifi/1.6/default/wifi_status_util.cpp
similarity index 87%
rename from wifi/1.5/default/wifi_status_util.cpp
rename to wifi/1.6/default/wifi_status_util.cpp
index eb8c869..3b18e53 100644
--- a/wifi/1.5/default/wifi_status_util.cpp
+++ b/wifi/1.6/default/wifi_status_util.cpp
@@ -19,7 +19,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 
 std::string legacyErrorToString(legacy_hal::wifi_error error) {
@@ -51,8 +51,7 @@
     }
 }
 
-WifiStatus createWifiStatus(WifiStatusCode code,
-                            const std::string& description) {
+WifiStatus createWifiStatus(WifiStatusCode code, const std::string& description) {
     return {code, description};
 }
 
@@ -60,8 +59,7 @@
     return createWifiStatus(code, "");
 }
 
-WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error,
-                                           const std::string& desc) {
+WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error, const std::string& desc) {
     switch (error) {
         case legacy_hal::WIFI_ERROR_UNINITIALIZED:
         case legacy_hal::WIFI_ERROR_NOT_AVAILABLE:
@@ -75,16 +73,13 @@
             return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS, desc);
 
         case legacy_hal::WIFI_ERROR_TIMED_OUT:
-            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN,
-                                    desc + ", timed out");
+            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", timed out");
 
         case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS:
-            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN,
-                                    desc + ", too many requests");
+            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", too many requests");
 
         case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY:
-            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN,
-                                    desc + ", out of memory");
+            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", out of memory");
 
         case legacy_hal::WIFI_ERROR_BUSY:
             return createWifiStatus(WifiStatusCode::ERROR_BUSY);
@@ -96,8 +91,7 @@
             return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown");
 
         default:
-            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN,
-                                    "unknown error");
+            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown error");
     }
 }
 
@@ -106,7 +100,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.5/default/wifi_status_util.h b/wifi/1.6/default/wifi_status_util.h
similarity index 89%
rename from wifi/1.5/default/wifi_status_util.h
rename to wifi/1.6/default/wifi_status_util.h
index 68f2168..ea1c294 100644
--- a/wifi/1.5/default/wifi_status_util.h
+++ b/wifi/1.6/default/wifi_status_util.h
@@ -24,20 +24,19 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_5 {
+namespace V1_6 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 
 std::string legacyErrorToString(legacy_hal::wifi_error error);
-WifiStatus createWifiStatus(WifiStatusCode code,
-                            const std::string& description);
+WifiStatus createWifiStatus(WifiStatusCode code, const std::string& description);
 WifiStatus createWifiStatus(WifiStatusCode code);
 WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error,
                                            const std::string& description);
 WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error);
 
 }  // namespace implementation
-}  // namespace V1_5
+}  // namespace V1_6
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
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
index 890d986..4d78640 100644
--- 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
@@ -41,8 +41,9 @@
   BANDWIDTH_80 = 4,
   BANDWIDTH_80P80 = 5,
   BANDWIDTH_160 = 6,
-  BANDWIDTH_2160 = 7,
-  BANDWIDTH_4320 = 8,
-  BANDWIDTH_6480 = 9,
-  BANDWIDTH_8640 = 10,
+  BANDWIDTH_320 = 7,
+  BANDWIDTH_2160 = 8,
+  BANDWIDTH_4320 = 9,
+  BANDWIDTH_6480 = 10,
+  BANDWIDTH_8640 = 11,
 }
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Generation.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Generation.aidl
index 6b60d17..af0e960 100644
--- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Generation.aidl
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Generation.aidl
@@ -40,4 +40,5 @@
   WIFI_STANDARD_11AC = 2,
   WIFI_STANDARD_11AX = 3,
   WIFI_STANDARD_11AD = 4,
+  WIFI_STANDARD_11BE = 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
index 844c838..8d8d7bb 100644
--- 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
@@ -43,4 +43,5 @@
   boolean enableHeMultiUserBeamformer;
   boolean enableHeTargetWakeTime;
   boolean enableEdmg;
+  boolean enable80211BE;
 }
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Bandwidth.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Bandwidth.aidl
index c982402..e605153 100644
--- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Bandwidth.aidl
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Bandwidth.aidl
@@ -29,8 +29,9 @@
     BANDWIDTH_80 = 4,
     BANDWIDTH_80P80 = 5,
     BANDWIDTH_160 = 6,
-    BANDWIDTH_2160 = 7,
-    BANDWIDTH_4320 = 8,
-    BANDWIDTH_6480 = 9,
-    BANDWIDTH_8640 = 10,
+    BANDWIDTH_320 = 7,
+    BANDWIDTH_2160 = 8,
+    BANDWIDTH_4320 = 9,
+    BANDWIDTH_6480 = 10,
+    BANDWIDTH_8640 = 11,
 }
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Generation.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Generation.aidl
index 2cda55b..f4e3eb0 100644
--- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Generation.aidl
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Generation.aidl
@@ -27,6 +27,7 @@
  * 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.
+ * WIFI_STANDARD_11BE = hw_mode is HOSTAPD_MODE_IEEE80211A and Extreme High Throughput supported.
  */
 @VintfStability
 @Backing(type="int")
@@ -37,4 +38,5 @@
     WIFI_STANDARD_11AC = 2,
     WIFI_STANDARD_11AX = 3,
     WIFI_STANDARD_11AD = 4,
+    WIFI_STANDARD_11BE = 5,
 }
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/HwModeParams.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/HwModeParams.aidl
index 210e99f..e66a24a 100644
--- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/HwModeParams.aidl
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/HwModeParams.aidl
@@ -68,4 +68,10 @@
      * Enable EDMG (802.11ay), this option is only allowed for the 60GHz band.
      */
     boolean enableEdmg;
+    /**
+     * Whether IEEE 802.11be (Extreme High Throughput) is enabled or not.
+     * Note: hw_mode=a is used to specify that 5 GHz band or 6 GHz band is
+     * used with Extreme High Throughput.
+     */
+    boolean enable80211BE;
 }
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
index ad36e68..bf5081e 100644
--- 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
@@ -39,4 +39,5 @@
   HT = 2,
   VHT = 3,
   HE = 4,
+  EHT = 5,
 }
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AuthAlgMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AuthAlgMask.aidl
index e8101ea..039d41d 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AuthAlgMask.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AuthAlgMask.aidl
@@ -19,7 +19,7 @@
 /**
  * Possible mask of values for AuthAlg param.
  * See /external/wpa_supplicant_8/src/common/defs.h for
- * all possible values (starting at WPA_AUTH_ALG_OPEN).
+ * the historical values (starting at WPA_AUTH_ALG_OPEN).
  */
 @VintfStability
 @Backing(type="int")
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupCipherMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupCipherMask.aidl
index d5b26ad..99e9da0 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupCipherMask.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupCipherMask.aidl
@@ -19,7 +19,7 @@
 /**
  * Possible mask of values for GroupCipher param.
  * See /external/wpa_supplicant_8/src/common/defs.h for
- * all possible values (starting at WPA_CIPHER_WEP40).
+ * the historical values (starting at WPA_CIPHER_WEP40).
  */
 @VintfStability
 @Backing(type="int")
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/KeyMgmtMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/KeyMgmtMask.aidl
index 3225585..f0c3345 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/KeyMgmtMask.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/KeyMgmtMask.aidl
@@ -19,7 +19,7 @@
 /**
  * Possible mask of values for KeyMgmt param.
  * See /external/wpa_supplicant_8/src/common/defs.h for
- * all possible values (starting at WPA_KEY_MGMT_IEEE8021X).
+ * the historical values (starting at WPA_KEY_MGMT_IEEE8021X).
  */
 @VintfStability
 @Backing(type="int")
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl
index ad134fa..7179fea 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl
@@ -19,7 +19,7 @@
 /**
  * Possible mask of values for PairwiseCipher param.
  * See /external/wpa_supplicant_8/src/common/defs.h for
- * all possible values (starting at WPA_CIPHER_NONE).
+ * the historical values (starting at WPA_CIPHER_NONE).
  */
 @VintfStability
 @Backing(type="int")
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ProtoMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ProtoMask.aidl
index 65c832b..dc3d80b 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ProtoMask.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ProtoMask.aidl
@@ -19,7 +19,7 @@
 /**
  * Possible mask of values for Proto param.
  * See /external/wpa_supplicant_8/src/common/defs.h for
- * all possible values (starting at WPA_PROTO_WPA).
+ * the historical values (starting at WPA_PROTO_WPA).
  */
 @VintfStability
 @Backing(type="int")
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiTechnology.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiTechnology.aidl
index 00c16b4..d364c75 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiTechnology.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiTechnology.aidl
@@ -39,4 +39,8 @@
      * For 802.11ax
      */
     HE = 4,
+    /**
+     * For 802.11be
+     */
+    EHT = 5,
 }