Remove separate_platform_variant entries. am: a049eb0faf am: 08643bdf3a am: d01346a45c am: 712226f9f3

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

Change-Id: Ie4f77679054520f94051716120b74f26819cff90
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1d74e21
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.vscode/
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
new file mode 100644
index 0000000..c172674
--- /dev/null
+++ b/audio/aidl/Android.bp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.audio.common",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/audio/common/PlaybackTrackMetadata.aidl",
+        "android/hardware/audio/common/RecordTrackMetadata.aidl",
+        "android/hardware/audio/common/SinkMetadata.aidl",
+        "android/hardware/audio/common/SourceMetadata.aidl",
+    ],
+    imports: [
+        "android.media.audio.common.types",
+    ],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: true,
+        },
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+    versions: [
+    ],
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/PlaybackTrackMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/PlaybackTrackMetadata.aidl
new file mode 100644
index 0000000..be4941c
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/PlaybackTrackMetadata.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable PlaybackTrackMetadata {
+  android.media.audio.common.AudioUsage usage = android.media.audio.common.AudioUsage.INVALID;
+  android.media.audio.common.AudioContentType contentType = android.media.audio.common.AudioContentType.UNKNOWN;
+  float gain;
+  android.media.audio.common.AudioChannelLayout channelMask;
+  @nullable android.media.audio.common.AudioDevice sourceDevice;
+  @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/RecordTrackMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/RecordTrackMetadata.aidl
new file mode 100644
index 0000000..8f667d1
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/RecordTrackMetadata.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable RecordTrackMetadata {
+  android.media.audio.common.AudioSource source = android.media.audio.common.AudioSource.SYS_RESERVED_INVALID;
+  float gain;
+  @nullable android.media.audio.common.AudioDevice destinationDevice;
+  android.media.audio.common.AudioChannelLayout channelMask;
+  @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SinkMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SinkMetadata.aidl
new file mode 100644
index 0000000..270147d
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SinkMetadata.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SinkMetadata {
+  android.hardware.audio.common.RecordTrackMetadata[] tracks;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SourceMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SourceMetadata.aidl
new file mode 100644
index 0000000..2d4a982
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SourceMetadata.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SourceMetadata {
+  android.hardware.audio.common.PlaybackTrackMetadata[] tracks;
+}
diff --git a/audio/aidl/android/hardware/audio/common/PlaybackTrackMetadata.aidl b/audio/aidl/android/hardware/audio/common/PlaybackTrackMetadata.aidl
new file mode 100644
index 0000000..9ce1e1f
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/PlaybackTrackMetadata.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.common;
+
+import android.media.audio.common.AudioChannelLayout;
+import android.media.audio.common.AudioContentType;
+import android.media.audio.common.AudioDevice;
+import android.media.audio.common.AudioUsage;
+
+/**
+ * Metadata of a playback track for an output stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable PlaybackTrackMetadata {
+    AudioUsage usage = AudioUsage.INVALID;
+    AudioContentType contentType = AudioContentType.UNKNOWN;
+    /**
+     * Non-negative linear gain (scaling) applied to track samples.
+     * 0 means muted, 1 is unity gain, 2 means double amplitude, etc.
+     */
+    float gain;
+    AudioChannelLayout channelMask;
+    /**
+     * Indicates the source of an output stream, can be left unspecified.
+     */
+    @nullable AudioDevice sourceDevice;
+    /**
+     * Tags from AudioTrack audio attributes. Tag is an additional use case
+     * qualifier complementing AudioUsage and AudioContentType. Tags are set by
+     * vendor specific applications and must be prefixed by "VX_". Vendor must
+     * namespace their tag names to avoid conflicts, for example:
+     * "VX_GOOGLE_VR". At least 3 characters are required for the vendor
+     * namespace.
+     */
+    @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/android/hardware/audio/common/RecordTrackMetadata.aidl b/audio/aidl/android/hardware/audio/common/RecordTrackMetadata.aidl
new file mode 100644
index 0000000..dfd88f1
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/RecordTrackMetadata.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.common;
+
+import android.media.audio.common.AudioChannelLayout;
+import android.media.audio.common.AudioContentType;
+import android.media.audio.common.AudioDevice;
+import android.media.audio.common.AudioSource;
+
+/**
+ * Metadata of a record track for an input stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable RecordTrackMetadata {
+    AudioSource source = AudioSource.SYS_RESERVED_INVALID;
+    /**
+     * Non-negative linear gain (scaling) applied to track samples.
+     * 0 means muted, 1 is unity gain, 2 means double amplitude, etc.
+     */
+    float gain;
+    /**
+     * Indicates the destination of an input stream, can be left unspecified.
+     */
+    @nullable AudioDevice destinationDevice;
+    AudioChannelLayout channelMask;
+    /**
+     * Tags from AudioRecord audio attributes. Tag is an additional use case
+     * qualifier complementing AudioUsage and AudioContentType. Tags are set by
+     * vendor specific applications and must be prefixed by "VX_". Vendor must
+     * namespace their tag names to avoid conflicts, for example:
+     * "VX_GOOGLE_VR". At least 3 characters are required for the vendor
+     * namespace.
+     */
+    @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/android/hardware/audio/common/SinkMetadata.aidl b/audio/aidl/android/hardware/audio/common/SinkMetadata.aidl
new file mode 100644
index 0000000..188c847
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/SinkMetadata.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.common;
+
+import android.hardware.audio.common.RecordTrackMetadata;
+
+/**
+ * Metadata of record tracks for an input stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable SinkMetadata {
+    RecordTrackMetadata[] tracks;
+}
diff --git a/audio/aidl/android/hardware/audio/common/SourceMetadata.aidl b/audio/aidl/android/hardware/audio/common/SourceMetadata.aidl
new file mode 100644
index 0000000..e9f23c6
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/SourceMetadata.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.common;
+
+import android.hardware.audio.common.PlaybackTrackMetadata;
+
+/**
+ * Metadata of playback tracks for an output stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable SourceMetadata {
+    PlaybackTrackMetadata[] tracks;
+}
diff --git a/audio/common/6.0/Android.bp b/audio/common/6.0/Android.bp
index fc54caf..91721fc 100644
--- a/audio/common/6.0/Android.bp
+++ b/audio/common/6.0/Android.bp
@@ -20,4 +20,8 @@
     ],
     gen_java: true,
     gen_java_constants: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.car.framework",
+    ],
 }
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index cfee26a..b280d7c 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -30,6 +30,7 @@
         "android.hardware.audio.common.test.utility",
         "audioclient-types-aidl-cpp",
         "libaudioclient_aidl_conversion",
+        "libstagefright_foundation",
     ],
     shared_libs: [
         "libbinder",
@@ -57,6 +58,7 @@
         "libmedia_helper",
         "android.hardware.audio@2.0",
         "android.hardware.audio.common@2.0",
+        "android.media.audio.common.types-V1-cpp",
     ],
     cflags: [
         "-DMAJOR_VERSION=2",
@@ -83,6 +85,7 @@
         "libmedia_helper",
         "android.hardware.audio@4.0",
         "android.hardware.audio.common@4.0",
+        "android.media.audio.common.types-V1-cpp",
     ],
     cflags: [
         "-DMAJOR_VERSION=4",
@@ -109,6 +112,7 @@
         "libmedia_helper",
         "android.hardware.audio@5.0",
         "android.hardware.audio.common@5.0",
+        "android.media.audio.common.types-V1-cpp",
     ],
     cflags: [
         "-DMAJOR_VERSION=5",
@@ -136,6 +140,7 @@
         "libmedia_helper",
         "android.hardware.audio@6.0",
         "android.hardware.audio.common@6.0",
+        "android.media.audio.common.types-V1-cpp",
     ],
     cflags: [
         "-DMAJOR_VERSION=6",
@@ -199,6 +204,7 @@
     static_libs: [
         "android.hardware.audio@6.0",
         "android.hardware.audio.common@6.0",
+        "android.media.audio.common.types-V1-cpp",
         "libaudiofoundation",
         "libaudiopolicycomponents",
         "libmedia_helper",
diff --git a/audio/policy/1.0/xml/api/current.txt b/audio/policy/1.0/xml/api/current.txt
index 29a9cd4..1478381 100644
--- a/audio/policy/1.0/xml/api/current.txt
+++ b/audio/policy/1.0/xml/api/current.txt
@@ -232,8 +232,10 @@
 
   public class ValueType {
     ctor public ValueType();
+    method public int getAndroid_type();
     method public String getLiteral();
     method public int getNumerical();
+    method public void setAndroid_type(int);
     method public void setLiteral(String);
     method public void setNumerical(int);
   }
diff --git a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
index 842e724..852ea77 100644
--- a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
+++ b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
@@ -190,6 +190,7 @@
     <xs:complexType name="valueType">
         <xs:attribute name="literal" type="xs:string" use="required"/>
         <xs:attribute name="numerical" type="xs:int" use="required"/>
+        <xs:attribute name="android_type" type="xs:int" use="optional"/>
     </xs:complexType>
 
     <xs:complexType name="attributesRefType">
diff --git a/automotive/audiocontrol/1.0/Android.bp b/automotive/audiocontrol/1.0/Android.bp
index 628793b..53ed78b 100644
--- a/automotive/audiocontrol/1.0/Android.bp
+++ b/automotive/audiocontrol/1.0/Android.bp
@@ -20,4 +20,8 @@
         "android.hidl.base@1.0",
     ],
     gen_java: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.car.framework",
+    ],
 }
diff --git a/automotive/audiocontrol/2.0/Android.bp b/automotive/audiocontrol/2.0/Android.bp
index 4d1fdbc..413cf48 100644
--- a/automotive/audiocontrol/2.0/Android.bp
+++ b/automotive/audiocontrol/2.0/Android.bp
@@ -24,4 +24,8 @@
         "android.hidl.safe_union@1.0",
     ],
     gen_java: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.car.framework",
+    ],
 }
diff --git a/automotive/audiocontrol/aidl/Android.bp b/automotive/audiocontrol/aidl/Android.bp
index 4acfd82..5e69429 100644
--- a/automotive/audiocontrol/aidl/Android.bp
+++ b/automotive/audiocontrol/aidl/Android.bp
@@ -17,6 +17,11 @@
     backend: {
         java: {
             sdk_version: "module_current",
+            min_sdk_version: "31",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.car.framework",
+            ],
         },
     },
     versions: ["1"],
diff --git a/automotive/can/1.0/default/libnl++/Android.bp b/automotive/can/1.0/default/libnl++/Android.bp
index 790adcd..2ebd1b4 100644
--- a/automotive/can/1.0/default/libnl++/Android.bp
+++ b/automotive/can/1.0/default/libnl++/Android.bp
@@ -35,6 +35,7 @@
         "protocols/generic/Generic.cpp",
         "protocols/generic/GenericMessageBase.cpp",
         "protocols/generic/Unknown.cpp",
+        "protocols/generic/families/Mac80211hwsim.cpp",
         "protocols/generic/families/Nl80211.cpp",
         "protocols/route/Link.cpp",
         "protocols/route/Route.cpp",
@@ -42,6 +43,7 @@
         "protocols/MessageDefinition.cpp",
         "protocols/NetlinkProtocol.cpp",
         "protocols/all.cpp",
+        "protocols/structs.cpp",
         "Attributes.cpp",
         "MessageFactory.cpp",
         "MessageMutator.cpp",
diff --git a/automotive/can/1.0/default/libnl++/MessageMutator.cpp b/automotive/can/1.0/default/libnl++/MessageMutator.cpp
index 00b48a6..de2a2b1 100644
--- a/automotive/can/1.0/default/libnl++/MessageMutator.cpp
+++ b/automotive/can/1.0/default/libnl++/MessageMutator.cpp
@@ -19,7 +19,7 @@
 namespace android::nl {
 
 MessageMutator::MessageMutator(nlmsghdr* buffer, size_t totalLen)
-    : mConstBuffer(buffer, totalLen), mMutableBuffer(buffer) {
+    : mMutableBuffer(buffer), mTotalLen(totalLen) {
     CHECK(totalLen >= sizeof(nlmsghdr));
 }
 
@@ -27,8 +27,12 @@
     return mMutableBuffer;
 }
 
+Buffer<nlmsghdr> MessageMutator::constBuffer() const {
+    return {mMutableBuffer, mTotalLen};
+}
+
 MessageMutator::operator Buffer<nlmsghdr>() const {
-    return mConstBuffer;
+    return constBuffer();
 }
 
 uint64_t MessageMutator::read(Buffer<nlattr> attr) const {
@@ -37,7 +41,8 @@
 
 void MessageMutator::write(Buffer<nlattr> attr, uint64_t val) const {
     const auto attrData = attr.data<uint64_t>();
-    const auto offset = mConstBuffer.getOffset(attrData);
+    // TODO(b/177251183): deduplicate this code against fragment()
+    const auto offset = constBuffer().getOffset(attrData);
     CHECK(offset.has_value()) << "Trying to write attribute that's not a member of this message";
 
     const auto writeableBuffer = reinterpret_cast<uint8_t*>(mMutableBuffer) + *offset;
@@ -47,4 +52,40 @@
     memcpy(writeableBuffer, &val, std::min(sizeof(val), attrSize));
 }
 
+MessageMutator MessageMutator::fragment(Buffer<nlmsghdr> buf) const {
+    const auto offset = constBuffer().getOffset(buf);
+    CHECK(offset.has_value()) << "Trying to modify a fragment outside of buffer range";
+
+    const auto writeableBuffer = reinterpret_cast<nlmsghdr*>(uintptr_t(mMutableBuffer) + *offset);
+    const auto len = buf.getRaw().len();
+    CHECK(len <= mTotalLen - *offset);
+
+    return {writeableBuffer, len};
+}
+
+MessageMutator::iterator MessageMutator::begin() const {
+    return {*this, constBuffer().begin()};
+}
+
+MessageMutator::iterator MessageMutator::end() const {
+    return {*this, constBuffer().end()};
+}
+
+MessageMutator::iterator::iterator(const MessageMutator& container,
+                                   Buffer<nlmsghdr>::iterator current)
+    : mContainer(container), mCurrent(current) {}
+
+MessageMutator::iterator MessageMutator::iterator::operator++() {
+    ++mCurrent;
+    return *this;
+}
+
+bool MessageMutator::iterator::operator==(const iterator& other) const {
+    return other.mCurrent == mCurrent;
+}
+
+const MessageMutator MessageMutator::iterator::operator*() const {
+    return mContainer.fragment(*mCurrent);
+}
+
 }  // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/Socket.cpp b/automotive/can/1.0/default/libnl++/Socket.cpp
index 514d9bb..cc1d839 100644
--- a/automotive/can/1.0/default/libnl++/Socket.cpp
+++ b/automotive/can/1.0/default/libnl++/Socket.cpp
@@ -68,6 +68,11 @@
     return true;
 }
 
+bool Socket::send(const Buffer<nlmsghdr>& msg, uint32_t destination) {
+    sockaddr_nl sa = {.nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = destination, .nl_groups = 0};
+    return send(msg, sa);
+}
+
 bool Socket::increaseReceiveBuffer(size_t maxSize) {
     if (maxSize == 0) {
         LOG(ERROR) << "Maximum receive size should not be zero";
@@ -157,6 +162,26 @@
     return {mFd.get(), events, 0};
 }
 
+bool Socket::addMembership(unsigned group) {
+    const auto res =
+            setsockopt(mFd.get(), SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group));
+    if (res < 0) {
+        PLOG(ERROR) << "Failed joining multicast group " << group;
+        return false;
+    }
+    return true;
+}
+
+bool Socket::dropMembership(unsigned group) {
+    const auto res =
+            setsockopt(mFd.get(), SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, &group, sizeof(group));
+    if (res < 0) {
+        PLOG(ERROR) << "Failed leaving multicast group " << group;
+        return false;
+    }
+    return true;
+}
+
 Socket::receive_iterator::receive_iterator(Socket& socket, bool end)
     : mSocket(socket), mIsEnd(end) {
     if (!end) receive();
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h b/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
index d759a0a..4cabb9a 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
@@ -138,7 +138,7 @@
     class raw_iterator : public iterator {
       public:
         iterator operator++() {
-            this->mCurrent.mData++;  // ignore alignment
+            ++this->mCurrent.mData;  // ignore alignment
             return *this;
         }
         const T& operator*() const { return *this->mCurrent.mData; }
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Message.h b/automotive/can/1.0/default/libnl++/include/libnl++/Message.h
index 50b3c4b..29f397d 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Message.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Message.h
@@ -34,7 +34,7 @@
  * a single instance can only be used by a single thread - the one owning the underlying buffer).
  */
 template <typename T>
-class Message {
+class Message : public Buffer<nlmsghdr> {
   public:
     /**
      * Validate buffer contents as a message carrying T data and create instance of parsed message.
@@ -51,7 +51,7 @@
 
         const auto attributes = buf.data<nlattr>(sizeof(T));
 
-        return Message<T>(nlHeader, dataHeader, attributes);
+        return Message<T>(buf, nlHeader, dataHeader, attributes);
     }
 
     /**
@@ -94,8 +94,9 @@
     const T* operator->() const { return &data; }
 
   private:
-    Message(const nlmsghdr& nlHeader, const T& dataHeader, Attributes attributes)
-        : header(nlHeader), data(dataHeader), attributes(attributes) {}
+    Message(Buffer<nlmsghdr> buffer, const nlmsghdr& nlHeader, const T& dataHeader,
+            Attributes attributes)
+        : Buffer<nlmsghdr>(buffer), header(nlHeader), data(dataHeader), attributes(attributes) {}
 };
 
 }  // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h b/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h
index 7d495e9..baadc44 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h
@@ -53,9 +53,27 @@
      */
     void write(Buffer<nlattr> attr, uint64_t val) const;
 
+    class iterator {
+      public:
+        iterator(const MessageMutator& container, Buffer<nlmsghdr>::iterator current);
+
+        iterator operator++();
+        bool operator==(const iterator& other) const;
+        const MessageMutator operator*() const;
+
+      protected:
+        const MessageMutator& mContainer;
+        Buffer<nlmsghdr>::iterator mCurrent;
+    };
+    iterator begin() const;
+    iterator end() const;
+
   private:
-    const Buffer<nlmsghdr> mConstBuffer;
     nlmsghdr* mMutableBuffer;
+    size_t mTotalLen;
+
+    Buffer<nlmsghdr> constBuffer() const;
+    MessageMutator fragment(Buffer<nlmsghdr> buf) const;
 };
 
 }  // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h b/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h
index 8ea3575..7ec0f7b 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h
@@ -95,6 +95,15 @@
     bool send(const Buffer<nlmsghdr>& msg, const sockaddr_nl& sa);
 
     /**
+     * Send Netlink message.
+     *
+     * \param msg Message to send.
+     * \param destination Destination PID.
+     * \return true, if succeeded.
+     */
+    bool send(const Buffer<nlmsghdr>& msg, uint32_t destination);
+
+    /**
      * Receive one or multiple Netlink messages.
      *
      * WARNING: the underlying buffer is owned by Socket class and the data is valid until the next
@@ -183,6 +192,22 @@
     pollfd preparePoll(short events = 0);
 
     /**
+     * Join a multicast group.
+     *
+     * \param group Group ID (*not* a bitfield)
+     * \return whether the operation succeeded
+     */
+    bool addMembership(unsigned group);
+
+    /**
+     * Leave a multicast group.
+     *
+     * \param group Group ID (*not* a bitfield)
+     * \return whether the operation succeeded
+     */
+    bool dropMembership(unsigned group);
+
+    /**
      * Live iterator continuously receiving messages from Netlink socket.
      *
      * Iteration ends when socket fails to receive a buffer.
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/generic/families/mac80211_hwsim.h b/automotive/can/1.0/default/libnl++/include/libnl++/generic/families/mac80211_hwsim.h
new file mode 100644
index 0000000..9b811f8
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/generic/families/mac80211_hwsim.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// API definitions from kernel drivers/net/wireless/mac80211_hwsim.h
+
+#define BIT(n) (1 << (n))
+
+enum hwsim_tx_control_flags {
+    HWSIM_TX_CTL_REQ_TX_STATUS = BIT(0),
+    HWSIM_TX_CTL_NO_ACK = BIT(1),
+    HWSIM_TX_STAT_ACK = BIT(2),
+};
+
+enum {
+    HWSIM_CMD_UNSPEC,
+    HWSIM_CMD_REGISTER,
+    HWSIM_CMD_FRAME,
+    HWSIM_CMD_TX_INFO_FRAME,
+    HWSIM_CMD_NEW_RADIO,
+    HWSIM_CMD_DEL_RADIO,
+    HWSIM_CMD_GET_RADIO,
+    HWSIM_CMD_ADD_MAC_ADDR,
+    HWSIM_CMD_DEL_MAC_ADDR,
+};
+
+enum {
+    HWSIM_ATTR_UNSPEC,
+    HWSIM_ATTR_ADDR_RECEIVER,
+    HWSIM_ATTR_ADDR_TRANSMITTER,
+    HWSIM_ATTR_FRAME,
+    HWSIM_ATTR_FLAGS,
+    HWSIM_ATTR_RX_RATE,
+    HWSIM_ATTR_SIGNAL,
+    HWSIM_ATTR_TX_INFO,
+    HWSIM_ATTR_COOKIE,
+    HWSIM_ATTR_CHANNELS,
+    HWSIM_ATTR_RADIO_ID,
+    HWSIM_ATTR_REG_HINT_ALPHA2,
+    HWSIM_ATTR_REG_CUSTOM_REG,
+    HWSIM_ATTR_REG_STRICT_REG,
+    HWSIM_ATTR_SUPPORT_P2P_DEVICE,
+    HWSIM_ATTR_USE_CHANCTX,
+    HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE,
+    HWSIM_ATTR_RADIO_NAME,
+    HWSIM_ATTR_NO_VIF,
+    HWSIM_ATTR_FREQ,
+    HWSIM_ATTR_PAD,
+    HWSIM_ATTR_TX_INFO_FLAGS,
+    HWSIM_ATTR_PERM_ADDR,
+    HWSIM_ATTR_IFTYPE_SUPPORT,
+    HWSIM_ATTR_CIPHER_SUPPORT,
+};
+
+struct hwsim_tx_rate {
+    int8_t idx;
+    uint8_t count;
+} __packed;
+static_assert(sizeof(hwsim_tx_rate) == 2);
+
+#undef BIT
diff --git a/automotive/can/1.0/default/libnl++/printer.cpp b/automotive/can/1.0/default/libnl++/printer.cpp
index f08897e..d540482 100644
--- a/automotive/can/1.0/default/libnl++/printer.cpp
+++ b/automotive/can/1.0/default/libnl++/printer.cpp
@@ -154,16 +154,19 @@
     }
 }
 
-std::string toString(const Buffer<nlmsghdr> hdr, int protocol, bool printPayload) {
-    if (!hdr.firstOk()) return "nlmsg{buffer overflow}";
+static void toStream(std::stringstream& ss, const Buffer<nlmsghdr> hdr, int protocol,
+                     bool printPayload) {
+    if (!hdr.firstOk()) {
+        ss << "nlmsg{buffer overflow}";
+        return;
+    }
 
-    std::stringstream ss;
     ss << std::setfill('0');
 
     auto protocolMaybe = protocols::get(protocol);
     if (!protocolMaybe.has_value()) {
         ss << "nlmsg{protocol=" << protocol << "}";
-        return ss.str();
+        return;
     }
     protocols::NetlinkProtocol& protocolDescr = *protocolMaybe;
 
@@ -187,7 +190,7 @@
     ss << ", crc=" << std::hex << std::setw(4) << crc16(hdr.data<uint8_t>()) << std::dec;
     ss << '}';
 
-    if (!printPayload) return ss.str();
+    if (!printPayload) return;
     ss << ' ';
 
     if (!msgDescMaybe.has_value()) {
@@ -210,6 +213,17 @@
     }
 
     ss << "}";
+}
+
+std::string toString(const Buffer<nlmsghdr> hdrs, int protocol, bool printPayload) {
+    std::stringstream ss;
+    bool first = true;
+    for (const auto hdr : hdrs) {
+        if (!first) ss << std::endl;
+        first = false;
+
+        toStream(ss, hdr, protocol, printPayload);
+    }
 
     return ss.str();
 }
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.cpp
index 1e1ad12..478c383 100644
--- a/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.cpp
@@ -16,6 +16,7 @@
 
 #include "Ctrl.h"
 
+#include "families/Mac80211hwsim.h"
 #include "families/Nl80211.h"
 
 #include <libnl++/Message.h>
@@ -68,12 +69,15 @@
     const auto familyId = msg.attributes.get<uint16_t>(CTRL_ATTR_FAMILY_ID);
     const auto familyName = msg.attributes.get<std::string>(CTRL_ATTR_FAMILY_NAME);
 
-    /* For now, we support just a single family. But if you add more, please define proper
+    /* For now, we support just two families. But if you add more, please define proper
      * abstraction and not hardcode every name and class here.
      */
     if (familyName == "nl80211") {
         mFamilyRegister[familyId] = std::make_shared<families::Nl80211>(familyId);
     }
+    if (familyName == "MAC80211_HWSIM") {
+        mFamilyRegister[familyId] = std::make_shared<families::Mac80211hwsim>(familyId);
+    }
 }
 
 }  // namespace android::nl::protocols::generic
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp
index b7b811b..f92d6c0 100644
--- a/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp
@@ -40,9 +40,9 @@
 
     ss << "genlmsghdr{";
     if (commandName.has_value()) {
-        ss << "cmd=" << unsigned(data.cmd);
-    } else {
         ss << "cmd=" << *commandName;
+    } else {
+        ss << "cmd=" << unsigned(data.cmd);
     }
     ss << ", version=" << unsigned(data.version);
     if (data.reserved != 0) ss << ", reserved=" << data.reserved;
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.cpp
new file mode 100644
index 0000000..f85309e
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Mac80211hwsim.h"
+
+#include "../../structs.h"
+#include "common.h"
+
+#include <libnl++/generic/families/mac80211_hwsim.h>
+
+namespace android::nl::protocols::generic::families {
+
+using DataType = AttributeDefinition::DataType;
+using Flags = AttributeDefinition::Flags;
+
+static void hwsim_tx_rateToStream(std::stringstream& ss, const Buffer<nlattr> attr);
+
+static const FlagsMap txControlFlags{
+        {HWSIM_TX_CTL_REQ_TX_STATUS, "REQ_TX"},
+        {HWSIM_TX_CTL_NO_ACK, "NO_ACK"},
+        {HWSIM_TX_STAT_ACK, "ACK"},
+};
+
+// clang-format off
+Mac80211hwsim::Mac80211hwsim(nlmsgtype_t familyId) : GenericMessageBase(familyId, "hwsim", {
+    {HWSIM_CMD_UNSPEC, "UNSPEC"},
+    {HWSIM_CMD_REGISTER, "REGISTER"},
+    {HWSIM_CMD_FRAME, "FRAME"},
+    {HWSIM_CMD_TX_INFO_FRAME, "TX_INFO_FRAME"},
+    {HWSIM_CMD_NEW_RADIO, "NEW_RADIO"},
+    {HWSIM_CMD_DEL_RADIO, "DEL_RADIO"},
+    {HWSIM_CMD_GET_RADIO, "GET_RADIO"},
+    {HWSIM_CMD_ADD_MAC_ADDR, "ADD_MAC_ADDR"},
+    {HWSIM_CMD_DEL_MAC_ADDR, "DEL_MAC_ADDR"},
+}, {
+    {HWSIM_ATTR_UNSPEC, {"UNSPEC"}},
+    {HWSIM_ATTR_ADDR_RECEIVER, {"ADDR_RECEIVER", DataType::Struct, hwaddrToStream}},
+    {HWSIM_ATTR_ADDR_TRANSMITTER, {"ADDR_TRANSMITTER", DataType::Struct, hwaddrToStream}},
+    {HWSIM_ATTR_FRAME, {"FRAME", DataType::Raw, AttributeMap{}, Flags::Verbose}},
+    {HWSIM_ATTR_FLAGS, {"FLAGS", DataType::Struct, flagsToStream(txControlFlags)}},
+    {HWSIM_ATTR_RX_RATE, {"RX_RATE", DataType::Uint}},
+    {HWSIM_ATTR_SIGNAL, {"SIGNAL", DataType::Uint}},
+    {HWSIM_ATTR_TX_INFO, {"TX_INFO", DataType::Struct, hwsim_tx_rateToStream}},
+    {HWSIM_ATTR_COOKIE, {"COOKIE", DataType::Uint}},
+    {HWSIM_ATTR_CHANNELS, {"CHANNELS", DataType::Uint}},
+    {HWSIM_ATTR_RADIO_ID, {"RADIO_ID", DataType::Uint}},
+    {HWSIM_ATTR_REG_HINT_ALPHA2, {"REG_HINT_ALPHA2", DataType::String}},
+    {HWSIM_ATTR_REG_CUSTOM_REG, {"REG_CUSTOM_REG", DataType::Uint}},
+    {HWSIM_ATTR_REG_STRICT_REG, {"REG_STRICT_REG", DataType::Flag}},
+    {HWSIM_ATTR_SUPPORT_P2P_DEVICE, {"SUPPORT_P2P_DEVICE", DataType::Flag}},
+    {HWSIM_ATTR_USE_CHANCTX, {"USE_CHANCTX", DataType::Flag}},
+    {HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE, {"DESTROY_RADIO_ON_CLOSE", DataType::Flag}},
+    {HWSIM_ATTR_RADIO_NAME, {"RADIO_NAME", DataType::String}},
+    {HWSIM_ATTR_NO_VIF, {"NO_VIF", DataType::Flag}},
+    {HWSIM_ATTR_FREQ, {"FREQ", DataType::Uint}},
+    {HWSIM_ATTR_PAD, {"PAD", DataType::Uint}},
+    {HWSIM_ATTR_TX_INFO_FLAGS, {"TX_INFO_FLAGS"}},  // hwsim_tx_rate_flag
+    {HWSIM_ATTR_PERM_ADDR, {"PERM_ADDR"}},
+    {HWSIM_ATTR_IFTYPE_SUPPORT, {"IFTYPE_SUPPORT", DataType::Uint}},  // NL80211_IFTYPE_STATION etc
+    {HWSIM_ATTR_CIPHER_SUPPORT, {"CIPHER_SUPPORT", DataType::Struct, arrayToStream<int32_t>}},
+}) {}
+// clang-format on
+
+static void hwsim_tx_rateToStream(std::stringstream& ss, const Buffer<nlattr> attr) {
+    ss << '{';
+    bool first = true;
+    for (const auto rate : attr.data<hwsim_tx_rate>().getRaw()) {
+        if (rate.idx == -1) continue;
+
+        ss << (int)rate.idx << ": " << (unsigned)rate.count;
+
+        if (!first) ss << ", ";
+        first = false;
+    }
+    ss << '}';
+}
+
+}  // namespace android::nl::protocols::generic::families
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.h b/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.h
new file mode 100644
index 0000000..c01eb93
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "../GenericMessageBase.h"
+
+namespace android::nl::protocols::generic::families {
+
+class Mac80211hwsim : public GenericMessageBase {
+  public:
+    Mac80211hwsim(nlmsgtype_t familyId);
+};
+
+}  // namespace android::nl::protocols::generic::families
diff --git a/automotive/can/1.0/default/libnl++/protocols/structs.cpp b/automotive/can/1.0/default/libnl++/protocols/structs.cpp
new file mode 100644
index 0000000..8ff71f0
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/protocols/structs.cpp
@@ -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.
+ */
+
+#include "structs.h"
+
+#include <iomanip>
+
+namespace android::nl::protocols {
+
+AttributeDefinition::ToStream flagsToStream(FlagsMap flags) {
+    return [flags](std::stringstream& ss, const Buffer<nlattr> attr) {
+        auto val = attr.data<uint64_t>().copyFirst();
+
+        bool first = true;
+        for (const auto& [flag, name] : flags) {
+            if ((val & flag) != flag) continue;
+            val &= ~flag;
+
+            if (!first) ss << '|';
+            first = false;
+
+            ss << name;
+        }
+
+        if (val == 0) return;
+
+        if (!first) ss << '|';
+        ss << std::hex << val << std::dec;
+    };
+}
+
+void hwaddrToStream(std::stringstream& ss, const Buffer<nlattr> attr) {
+    ss << std::hex;
+    bool first = true;
+    for (const auto byte : attr.data<uint8_t>().getRaw()) {
+        if (!first) ss << ':';
+        first = false;
+
+        ss << std::setw(2) << unsigned(byte);
+    }
+    ss << std::dec;
+}
+
+}  // namespace android::nl::protocols
diff --git a/automotive/can/1.0/default/libnl++/protocols/structs.h b/automotive/can/1.0/default/libnl++/protocols/structs.h
index 44c17b8..f3a8c44 100644
--- a/automotive/can/1.0/default/libnl++/protocols/structs.h
+++ b/automotive/can/1.0/default/libnl++/protocols/structs.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include "MessageDefinition.h"
+
 #include <sstream>
 
 namespace android::nl::protocols {
@@ -30,4 +32,9 @@
     ss << '}';
 }
 
+typedef std::map<uint64_t, std::string> FlagsMap;
+AttributeDefinition::ToStream flagsToStream(FlagsMap flags);
+
+void hwaddrToStream(std::stringstream& ss, const Buffer<nlattr> attr);
+
 }  // namespace android::nl::protocols
diff --git a/automotive/can/1.0/tools/libprotocan/Android.bp b/automotive/can/1.0/tools/libprotocan/Android.bp
new file mode 100644
index 0000000..76c238b
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/Android.bp
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+    name: "libprotocan",
+    defaults: ["android.hardware.automotive.vehicle@2.0-protocan-defaults"],
+    vendor: true,
+    srcs: [
+        "Checksum.cpp",
+        "MessageCounter.cpp",
+        "MessageDef.cpp",
+        "MessageInjector.cpp",
+        "Signal.cpp",
+    ],
+    export_include_dirs: ["include"],
+
+    shared_libs: [
+        "android.hardware.automotive.can@1.0",
+    ],
+}
diff --git a/automotive/can/1.0/tools/libprotocan/Checksum.cpp b/automotive/can/1.0/tools/libprotocan/Checksum.cpp
new file mode 100644
index 0000000..72fb0af
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/Checksum.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/Checksum.h>
+
+namespace android::hardware::automotive::protocan {
+
+Checksum::Checksum(Signal signal, formula f) : mSignal(signal), mFormula(f) {}
+
+void Checksum::update(can::V1_0::CanMessage& msg) const {
+  mSignal.set(msg, 0);
+  mSignal.set(msg, mFormula(msg) % (mSignal.maxValue + 1));
+}
+
+}  // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/MessageCounter.cpp b/automotive/can/1.0/tools/libprotocan/MessageCounter.cpp
new file mode 100644
index 0000000..ef9882f
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/MessageCounter.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/MessageCounter.h>
+
+#include <android-base/logging.h>
+
+namespace android::hardware::automotive::protocan {
+
+/** Whether to log counter state messages. */
+static constexpr bool kSuperVerbose = false;
+
+MessageCounter::MessageCounter(Signal signal) : upperBound(signal.maxValue + 1), mSignal(signal) {}
+
+Signal::value MessageCounter::next() const {
+  CHECK(mCurrent.has_value()) << "Counter not initialized. Did you call isReady?";
+  return (*mCurrent + 1) % upperBound;
+}
+
+void MessageCounter::read(const can::V1_0::CanMessage& msg) {
+    auto val = mSignal.get(msg);
+
+    if (!mCurrent.has_value()) {
+        LOG(VERBOSE) << "Got first counter val of " << val;
+        mCurrent = val;
+        return;
+    }
+
+    auto nextVal = next();
+    if (nextVal == val) {
+        if constexpr (kSuperVerbose) {
+            LOG(VERBOSE) << "Got next counter val of " << nextVal;
+        }
+        mCurrent = nextVal;
+    } else {
+        LOG(DEBUG) << "Ignoring next counter val of " << val << ", waiting for " << nextVal;
+    }
+}
+
+bool MessageCounter::isReady() const { return mCurrent.has_value(); }
+
+void MessageCounter::increment(can::V1_0::CanMessage& msg) {
+  auto newVal = next();
+  mCurrent = newVal;
+  mSignal.set(msg, newVal);
+}
+
+}  // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/MessageDef.cpp b/automotive/can/1.0/tools/libprotocan/MessageDef.cpp
new file mode 100644
index 0000000..23ce1df
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/MessageDef.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/MessageDef.h>
+
+#include <android-base/logging.h>
+
+namespace android::hardware::automotive::protocan {
+
+using can::V1_0::CanMessage;
+using can::V1_0::CanMessageId;
+
+MessageDef::MessageDef(CanMessageId id, uint16_t len, std::map<std::string, Signal> signals,
+                       std::optional<Signal> counter, std::optional<Checksum> checksum)
+    : id(id), kLen(len), kSignals(std::move(signals)), kCounter(counter), kChecksum(checksum) {}
+
+const Signal& MessageDef::operator[](const std::string& signalName) const {
+  auto it = kSignals.find(signalName);
+  CHECK(it != kSignals.end()) << "Signal " << signalName << " doesn't exist";
+  return it->second;
+}
+
+CanMessage MessageDef::makeDefault() const {
+  CanMessage msg = {};
+  msg.id = id;
+  msg.payload.resize(kLen);
+
+  for (auto const& [name, signal] : kSignals) {
+    signal.setDefault(msg);
+  }
+
+  return msg;
+}
+
+MessageCounter MessageDef::makeCounter() const {
+  CHECK(kCounter.has_value()) << "Can't build a counter for message without such signal";
+  return MessageCounter(*kCounter);
+}
+
+void MessageDef::updateChecksum(can::V1_0::CanMessage& msg) const {
+  if (!kChecksum.has_value()) return;
+  kChecksum->update(msg);
+}
+
+bool MessageDef::validate(const can::V1_0::CanMessage& msg) const {
+    return msg.payload.size() >= kLen;
+}
+
+}  // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/MessageInjector.cpp b/automotive/can/1.0/tools/libprotocan/MessageInjector.cpp
new file mode 100644
index 0000000..7c45eaa
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/MessageInjector.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/MessageInjector.h>
+
+#include <android-base/logging.h>
+
+#include <thread>
+
+namespace android::hardware::automotive::protocan {
+
+/** Whether to log injected messages. */
+static constexpr bool kSuperVerbose = true;
+
+using namespace std::literals::chrono_literals;
+
+using can::V1_0::CanMessage;
+using can::V1_0::CanMessageId;
+using can::V1_0::ICanBus;
+using can::V1_0::Result;
+
+MessageInjector::MessageInjector(MessageDef msgDef,
+                                 std::optional<std::chrono::milliseconds> interMessageDelay)
+    : kMsgDef(std::move(msgDef)),
+      kInterMessageDelay(interMessageDelay),
+      mCounter(msgDef.makeCounter()) {}
+
+void MessageInjector::inject(const CanMessage& msg) { inject({msg}); }
+
+void MessageInjector::inject(const std::initializer_list<can::V1_0::CanMessage> msgs) {
+  std::lock_guard<std::mutex> lock(mMessagesGuard);
+  for (const auto& msg : msgs) {
+    if constexpr (kSuperVerbose) {
+      LOG(VERBOSE) << "Message scheduled for injection: " << toString(msg);
+    }
+
+    mMessages.push(msg);
+  }
+}
+
+void MessageInjector::processQueueLocked(can::V1_0::ICanBus& bus) {
+  if (mMessages.empty() || !mCounter.isReady()) return;
+
+  auto paddingMessagesCount = mCounter.upperBound - (mMessages.size() % mCounter.upperBound);
+  auto padMessage = kMsgDef.makeDefault();
+  for (unsigned i = 0; i < paddingMessagesCount; i++) {
+    mMessages.push(padMessage);
+  }
+
+  while (!mMessages.empty()) {
+    auto&& outMsg = mMessages.front();
+
+    mCounter.increment(outMsg);
+    kMsgDef.updateChecksum(outMsg);
+
+    if constexpr (kSuperVerbose) {
+      LOG(VERBOSE) << "Injecting message: " << toString(outMsg);
+    }
+    auto result = bus.send(outMsg);
+    if (result != Result::OK) {
+      LOG(ERROR) << "Message injection failed: " << toString(result);
+    }
+
+    mMessages.pop();
+
+    // This would block onReceive, but the class is not supposed to be used in production anyway
+    // (see MessageInjector docstring).
+    if (kInterMessageDelay.has_value()) {
+      std::this_thread::sleep_for(*kInterMessageDelay);
+    }
+  }
+}
+
+void MessageInjector::onReceive(ICanBus& bus, const CanMessage& msg) {
+    if (!kMsgDef.validate(msg)) return;
+
+    std::lock_guard<std::mutex> lock(mMessagesGuard);
+
+    mCounter.read(msg);
+    processQueueLocked(bus);
+}
+
+MessageInjectorManager::MessageInjectorManager(
+    std::initializer_list<std::shared_ptr<MessageInjector>> injectors) {
+  std::transform(injectors.begin(), injectors.end(), std::inserter(mInjectors, mInjectors.end()),
+                 [](const std::shared_ptr<MessageInjector>& injector) {
+                   return std::make_pair(injector->kMsgDef.id, std::move(injector));
+                 });
+}
+
+void MessageInjectorManager::onReceive(sp<ICanBus> bus, const CanMessage& msg) {
+  auto it = mInjectors.find(msg.id);
+  if (it == mInjectors.end()) return;
+  it->second->onReceive(*bus, msg);
+}
+
+}  // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/Signal.cpp b/automotive/can/1.0/tools/libprotocan/Signal.cpp
new file mode 100644
index 0000000..bc3e070
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/Signal.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/Signal.h>
+
+#include <android-base/logging.h>
+
+namespace android::hardware::automotive::protocan {
+
+static uint8_t calculateLastByteMask(uint16_t start, uint8_t length) {
+  unsigned lastByteBits = (start + length) % 8;
+  unsigned lastBytePadding = (8 - lastByteBits) % 8;
+  return 0xFF >> lastBytePadding;
+}
+
+static uint8_t calculateFirstByteMask(uint16_t firstByte, uint8_t firstBit, uint16_t lastByte,
+                                      uint8_t lastMask) {
+  uint8_t firstMask = 0xFF << firstBit;
+  if (firstByte == lastByte) firstMask &= lastMask;
+  return firstMask;
+}
+
+Signal::Signal(uint16_t start, uint8_t length, value defVal)
+    : maxValue((1u << length) - 1),
+      kFirstByte(start / 8),
+      kFirstBit(start % 8),
+      kFirstByteBits(8 - kFirstBit),
+      kLastByte((start + length - 1) / 8),
+      kLastMask(calculateLastByteMask(start, length)),
+      kFirstMask(calculateFirstByteMask(kFirstByte, kFirstBit, kLastByte, kLastMask)),
+      kDefVal(defVal) {
+  CHECK(length > 0) << "Signal length must not be zero";
+}
+
+Signal::value Signal::get(const can::V1_0::CanMessage& msg) const {
+    CHECK(msg.payload.size() > kLastByte)
+            << "Message is too short. Did you call MessageDef::validate?";
+
+    Signal::value v = 0;
+    if (kLastByte != kFirstByte) v = kLastMask & msg.payload[kLastByte];
+
+    for (int i = kLastByte - 1; i > kFirstByte; i--) {
+        v = (v << 8) | msg.payload[i];
+    }
+
+    return (v << kFirstByteBits) | ((msg.payload[kFirstByte] & kFirstMask) >> kFirstBit);
+}
+
+void Signal::set(can::V1_0::CanMessage& msg, Signal::value val) const {
+  CHECK(msg.payload.size() > kLastByte)
+      << "Signal requires message of length " << (kLastByte + 1)
+      << " which is beyond message length of " << msg.payload.size();
+
+  uint8_t firstByte = val << kFirstBit;
+  val >>= kFirstByteBits;
+
+  msg.payload[kFirstByte] = (msg.payload[kFirstByte] & ~kFirstMask) | (firstByte & kFirstMask);
+
+  for (int i = kFirstByte + 1; i < kLastByte; i++) {
+    msg.payload[i] = val & 0xFF;
+    val >>= 8;
+  }
+
+  if (kLastByte != kFirstByte) {
+    msg.payload[kLastByte] = (msg.payload[kLastByte] & ~kLastMask) | (val & kLastMask);
+  }
+}
+
+void Signal::setDefault(can::V1_0::CanMessage& msg) const { set(msg, kDefVal); }
+
+}  // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/include/libprotocan/Checksum.h b/automotive/can/1.0/tools/libprotocan/include/libprotocan/Checksum.h
new file mode 100644
index 0000000..ff1dc91
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/include/libprotocan/Checksum.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/automotive/can/1.0/types.h>
+#include <libprotocan/Signal.h>
+
+namespace android::hardware::automotive::protocan {
+
+class Checksum {
+ public:
+  using formula = std::function<Signal::value(const can::V1_0::CanMessage&)>;
+
+  Checksum(Signal signal, formula f);
+
+  void update(can::V1_0::CanMessage& msg) const;
+
+ private:
+  const Signal mSignal;
+  const formula mFormula;
+};
+
+}  // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageCounter.h b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageCounter.h
new file mode 100644
index 0000000..56113be
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageCounter.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/automotive/can/1.0/types.h>
+#include <libprotocan/Signal.h>
+
+namespace android::hardware::automotive::protocan {
+
+class MessageCounter {
+ public:
+  const Signal::value upperBound;
+
+  MessageCounter(Signal signal);
+
+  /**
+   * Parse CAN message sent by external ECU to determine current counter value.
+   */
+  void read(const can::V1_0::CanMessage& msg);
+
+  /**
+   * States whether current counter value is determined.
+   */
+  bool isReady() const;
+
+  /**
+   * Increment current counter value and set it in a new message.
+   *
+   * Caller must check isReady() at least once before calling this method.
+   */
+  void increment(can::V1_0::CanMessage& msg);
+
+ private:
+  const Signal mSignal;
+
+  std::optional<Signal::value> mCurrent = std::nullopt;
+
+  Signal::value next() const;
+};
+
+}  // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageDef.h b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageDef.h
new file mode 100644
index 0000000..79b21e1
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageDef.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/automotive/can/1.0/types.h>
+#include <libprotocan/Checksum.h>
+#include <libprotocan/MessageCounter.h>
+#include <libprotocan/Signal.h>
+
+namespace android::hardware::automotive::protocan {
+
+/**
+ * CAN message definition (not the actual message data).
+ *
+ * Describes static message properties (message ID, signals etc).
+ */
+class MessageDef {
+ public:
+  const can::V1_0::CanMessageId id;
+
+  /**
+   * Create message definition.
+   *
+   * Currently only constant length messages are supported.
+   *
+   * \param id CAN message ID
+   * \param len CAN message length
+   * \param signals CAN signal definitions
+   * \param counter Designated CAN signal definition for message counter, if the message has one
+   * \param checksum Designated CAN signal definition for payload checksum, if the message has one
+   */
+  MessageDef(can::V1_0::CanMessageId id, uint16_t len, std::map<std::string, Signal> signals,
+             std::optional<Signal> counter = std::nullopt,
+             std::optional<Checksum> checksum = std::nullopt);
+
+  const Signal& operator[](const std::string& signalName) const;
+
+  can::V1_0::CanMessage makeDefault() const;
+  MessageCounter makeCounter() const;
+
+  void updateChecksum(can::V1_0::CanMessage& msg) const;
+
+  /**
+   * Validate the message payload is large enough to hold all the signals.
+   */
+  bool validate(const can::V1_0::CanMessage& msg) const;
+
+private:
+  const uint16_t kLen;
+  const std::map<std::string, Signal> kSignals;
+  const std::optional<Signal> kCounter;
+  const std::optional<Checksum> kChecksum;
+};
+
+}  // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageInjector.h b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageInjector.h
new file mode 100644
index 0000000..b0ea260
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageInjector.h
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+#include <android/hardware/automotive/can/1.0/ICanBus.h>
+#include <libprotocan/MessageCounter.h>
+#include <libprotocan/MessageDef.h>
+#include <utils/Mutex.h>
+
+#include <queue>
+
+namespace android::hardware::automotive::protocan {
+
+class MessageInjectorManager;
+
+/**
+ * Injects CAN messages with a counter to an existing system.
+ *
+ * This class is NOT meant to use in production - there should be no need to inject counted CAN
+ * messages where the other sender is also broadcasting them. If this is the case, it may be a sign
+ * your CAN network needs a redesign. This tool is intended for use for testing and demo purposes.
+ */
+class MessageInjector {
+ public:
+  MessageInjector(MessageDef msgDef, std::optional<std::chrono::milliseconds> interMessageDelay);
+
+  void inject(const can::V1_0::CanMessage& msg);
+  void inject(const std::initializer_list<can::V1_0::CanMessage> msgs);
+
+ private:
+  const MessageDef kMsgDef;
+  const std::optional<std::chrono::milliseconds> kInterMessageDelay;
+  MessageCounter mCounter;
+
+  mutable std::mutex mMessagesGuard;
+  std::queue<can::V1_0::CanMessage> mMessages GUARDED_BY(mMessagesGuard);
+
+  void onReceive(can::V1_0::ICanBus& bus, const can::V1_0::CanMessage& msg);
+  void processQueueLocked(can::V1_0::ICanBus& bus);
+
+  friend class MessageInjectorManager;
+
+  DISALLOW_COPY_AND_ASSIGN(MessageInjector);
+};
+
+/**
+ * Routes intercepted messages to MessageInjector instances configured to handle specific CAN
+ * message (CAN message ID). Intercepted messages from other nodes in CAN network are used to read
+ * current counter value in order to spoof the next packet.
+ */
+class MessageInjectorManager {
+ public:
+  MessageInjectorManager(std::initializer_list<std::shared_ptr<MessageInjector>> injectors);
+
+  void onReceive(sp<can::V1_0::ICanBus> bus, const can::V1_0::CanMessage& msg);
+
+ private:
+  std::map<can::V1_0::CanMessageId, std::shared_ptr<MessageInjector>> mInjectors;
+
+  DISALLOW_COPY_AND_ASSIGN(MessageInjectorManager);
+};
+
+}  // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/include/libprotocan/Signal.h b/automotive/can/1.0/tools/libprotocan/include/libprotocan/Signal.h
new file mode 100644
index 0000000..7c0f119
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/include/libprotocan/Signal.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+#include <android/hardware/automotive/can/1.0/types.h>
+
+namespace android::hardware::automotive::protocan {
+
+/**
+ * TODO(twasilczyk): right now, only Little Endian signals are supported.
+ */
+class Signal {
+ public:
+  using value = uint64_t;
+
+  const value maxValue;
+
+  Signal(uint16_t start, uint8_t length, value defVal = 0);
+
+  value get(const can::V1_0::CanMessage& msg) const;
+  void set(can::V1_0::CanMessage& msg, value val) const;
+  void setDefault(can::V1_0::CanMessage& msg) const;
+
+ private:
+  const uint16_t kFirstByte;     ///< Index of first byte that holds the signal
+  const uint8_t kFirstBit;       ///< Index of first bit within first byte
+  const uint8_t kFirstByteBits;  ///< How many bits of the first byte belong to the signal
+  const uint16_t kLastByte;      ///< Index of last byte that holds the signal
+  const uint8_t kLastMask;       ///< Bits of the last byte that belong to the signal
+  const uint8_t kFirstMask;      ///< Bits of the first byte that belong to the signal
+
+  const value kDefVal;
+};
+
+}  // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/tests/Android.bp b/automotive/can/1.0/tools/libprotocan/tests/Android.bp
new file mode 100644
index 0000000..251cc06
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/tests/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+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: "libprotocan_signal_test",
+    defaults: ["android.hardware.automotive.can@defaults"],
+    vendor: true,
+    gtest: true,
+    srcs: ["libprotocan_signal_test.cpp"],
+    static_libs: [
+        "libprotocan",
+    ],
+    shared_libs: [
+        "android.hardware.automotive.can@1.0",
+        "libhidlbase",
+    ],
+}
diff --git a/automotive/can/1.0/tools/libprotocan/tests/libprotocan_signal_test.cpp b/automotive/can/1.0/tools/libprotocan/tests/libprotocan_signal_test.cpp
new file mode 100644
index 0000000..19c1209
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/tests/libprotocan_signal_test.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/Signal.h>
+
+#include <gtest/gtest.h>
+
+namespace android::hardware::automotive::protocan::unittest {
+
+TEST(SignalTest, TestGetSingleBytes) {
+  can::V1_0::CanMessage msg = {};
+  msg.payload = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+  for (unsigned i = 0; i < msg.payload.size(); i++) {
+    Signal signal(8 * i, 8);
+    ASSERT_EQ(i, signal.get(msg));
+  }
+}
+
+TEST(SignalTest, TestSetSingleBytes) {
+  std::vector<can::V1_0::CanMessage> msgs = {{}, {}, {}};
+  msgs[0].payload = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+  msgs[1].payload = {0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB};
+  msgs[2].payload = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+  for (unsigned i = 0; i < msgs[0].payload.size(); i++) {
+    Signal signal(8 * i, 8);
+
+    for (auto&& msgOriginal : msgs) {
+      auto msgModified = msgOriginal;
+      signal.set(msgModified, 0xBA);
+
+      auto msgExpected = msgOriginal;
+      msgExpected.payload[i] = 0xBA;
+
+      ASSERT_EQ(msgExpected, msgModified) << "i=" << i;
+    }
+  }
+}
+
+TEST(SignalTest, TestGetStart4) {
+  /* Data generated with Python3:
+   *
+   * from cantools.database.can import *
+   * hex(Message(1, 'm', 4, [Signal('s', 4, 16, byte_order='little_endian')]).
+   *     decode(b'\xde\xad\xbe\xef')['s'])
+   */
+
+  can::V1_0::CanMessage msg = {};
+  msg.payload = {0xDE, 0xAD, 0xBE, 0xEF};
+  can::V1_0::CanMessage msg2 = {};
+  msg2.payload = {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD};
+
+  Signal s0_4(0, 4);
+  Signal s4_4(4, 4);
+  Signal s4_8(4, 8);
+  Signal s4_16(4, 16);
+  Signal s4_28(4, 28);
+  Signal s12_8(12, 8);
+  Signal s12_12(12, 12);
+  Signal s12_16(12, 16);
+  Signal s12_20(12, 20);
+  Signal s12_32(12, 32);
+
+  ASSERT_EQ(0xEu, s0_4.get(msg));
+  ASSERT_EQ(0xDu, s4_4.get(msg));
+  ASSERT_EQ(0xDDu, s4_8.get(msg));
+  ASSERT_EQ(0xEADDu, s4_16.get(msg));
+  ASSERT_EQ(0xEFBEADDu, s4_28.get(msg));
+  ASSERT_EQ(0xEAu, s12_8.get(msg));
+  ASSERT_EQ(0xBEAu, s12_12.get(msg));
+  ASSERT_EQ(0xFBEAu, s12_16.get(msg));
+  ASSERT_EQ(0xEFBEAu, s12_20.get(msg));
+  ASSERT_EQ(0xDDEEFBEAu, s12_32.get(msg2));
+}
+
+TEST(SignalTest, TestGet64) {
+  /* Data generated with Python3:
+   *
+   * from cantools.database.can import *
+   * hex(Message(1, 'm', 9, [Signal('s', 4, 64, byte_order='little_endian')]).
+   *     decode(b'\xde\xad\xbe\xef\xab\xbc\xcd\xde\xef')['s'])
+   */
+
+  can::V1_0::CanMessage msg = {};
+  msg.payload = {0xDE, 0xAD, 0xBE, 0xEF, 0xAB, 0xBC, 0xCD, 0xDE, 0xEF};
+
+  Signal s0_64(0, 64);
+  Signal s8_64(8, 64);
+  Signal s4_64(4, 64);
+  Signal s1_64(1, 64);
+
+  ASSERT_EQ(0xDECDBCABEFBEADDEu, s0_64.get(msg));
+  ASSERT_EQ(0xEFDECDBCABEFBEADu, s8_64.get(msg));
+  ASSERT_EQ(0xFDECDBCABEFBEADDu, s4_64.get(msg));
+  ASSERT_EQ(0xEF66DE55F7DF56EFu, s1_64.get(msg));
+}
+
+TEST(SignalTest, TestGetAllStarts) {
+  /* Data generated with Python3:
+   *
+   * from cantools.database.can import *
+   * hex(Message(1, 'm', 6, [Signal('s', 0, 20, byte_order='little_endian')]).
+   *     decode(b'\xde\xad\xbe\xef\xde\xad')['s'])
+   */
+
+  std::map<int, Signal::value> shifts = {
+      {0, 0xEADDEu}, {1, 0xF56EFu}, {2, 0xFAB77u}, {3, 0x7D5BBu}, {4, 0xBEADDu},  {5, 0xDF56Eu},
+      {6, 0xEFAB7u}, {7, 0xF7D5Bu}, {8, 0xFBEADu}, {9, 0x7DF56u}, {10, 0xBEFABu}, {11, 0xDF7D5u},
+  };
+
+  can::V1_0::CanMessage msg = {};
+  msg.payload = {0xDE, 0xAD, 0xBE, 0xEF, 0xCC, 0xCC};
+
+  for (auto const& [start, expected] : shifts) {
+    Signal s(start, 20);
+    ASSERT_EQ(expected, s.get(msg)) << "shift of " << start << " failed";
+  }
+}
+
+TEST(SignalTest, TestSetStart4) {
+  /* Data generated with Python3:
+   *
+   * from cantools.database.can import *
+   * so=4 ; sl=8
+   * md = Message(1, 'm', 4, [Signal('a1', 0, so), Signal('a2', so+sl, 32-so-sl),
+   *     Signal('s', so, sl, byte_order='little_endian')])
+   * m = md.decode(b'\xcc\xcc\xcc\xcc')
+   * m['s'] = 0xDE
+   * binascii.hexlify(md.encode(m)).upper()
+   */
+  typedef struct {
+    int start;
+    int length;
+    Signal::value setValue;
+    hidl_vec<uint8_t> payload;
+  } case_t;
+
+  std::vector<case_t> cases = {
+      {0, 4, 0xDu, {0xCD, 0xCC, 0xCC, 0xCC}},       {4, 4, 0xDu, {0xDC, 0xCC, 0xCC, 0xCC}},
+      {4, 8, 0xDEu, {0xEC, 0xCD, 0xCC, 0xCC}},      {4, 16, 0xDEADu, {0xDC, 0xEA, 0xCD, 0xCC}},
+      {4, 24, 0xDEADBEu, {0xEC, 0xDB, 0xEA, 0xCD}}, {4, 28, 0xDEADBEEu, {0xEC, 0xBE, 0xAD, 0xDE}},
+      {12, 8, 0xDEu, {0xCC, 0xEC, 0xCD, 0xCC}},     {12, 12, 0xDEAu, {0xCC, 0xAC, 0xDE, 0xCC}},
+      {12, 16, 0xDEADu, {0xCC, 0xDC, 0xEA, 0xCD}},  {12, 20, 0xDEADBu, {0xCC, 0xBC, 0xAD, 0xDE}},
+  };
+
+  can::V1_0::CanMessage msg = {};
+  msg.payload = {0xCC, 0xCC, 0xCC, 0xCC};
+
+  for (auto const& tcase : cases) {
+    Signal s(tcase.start, tcase.length);
+
+    can::V1_0::CanMessage expectedMsg = {};
+    expectedMsg.payload = tcase.payload;
+
+    can::V1_0::CanMessage editedMsg = msg;
+    s.set(editedMsg, tcase.setValue);
+
+    ASSERT_EQ(expectedMsg, editedMsg) << " set(" << tcase.start << ", " << tcase.length << ")";
+  }
+}
+
+TEST(SignalTest, TestSetAllStarts) {
+  /* Data generated with Python3:
+   * from cantools.database.can import *
+   * import binascii
+   * import textwrap
+   *
+   * length = 20
+   * for start in range(0, 32 - length):
+   *     signals = [Signal('s', start, length, byte_order='little_endian')]
+   *     if start > 0: signals.append(Signal('a', 0, start, byte_order='little_endian'))
+   *     signals.append(Signal('b', start + length, 32 - start - length,
+   *         byte_order='little_endian'))
+   *
+   *     md = Message(1, 'm', 4, signals)
+   *     m = md.decode(b'\xcc\xcc\xcc\xcc')
+   *     m['s'] = 0xDEADB
+   *     out = binascii.hexlify(md.encode(m)).decode('ascii').upper()
+   *     out = ', '.join(['0x{}'.format(v) for v in textwrap.wrap(out, 2)])
+   *     print('{{ {:d}, {{ {:s} }}}},'.format(start, out))
+   */
+
+  std::map<int, hidl_vec<uint8_t>> shifts = {
+      {0, {0xDB, 0xEA, 0xCD, 0xCC}}, {1, {0xB6, 0xD5, 0xDB, 0xCC}},  {2, {0x6C, 0xAB, 0xF7, 0xCC}},
+      {3, {0xDC, 0x56, 0xEF, 0xCC}}, {4, {0xBC, 0xAD, 0xDE, 0xCC}},  {5, {0x6C, 0x5B, 0xBD, 0xCD}},
+      {6, {0xCC, 0xB6, 0x7A, 0xCF}}, {7, {0xCC, 0x6D, 0xF5, 0xCE}},  {8, {0xCC, 0xDB, 0xEA, 0xCD}},
+      {9, {0xCC, 0xB6, 0xD5, 0xDB}}, {10, {0xCC, 0x6C, 0xAB, 0xF7}}, {11, {0xCC, 0xDC, 0x56, 0xEF}},
+  };
+
+  can::V1_0::CanMessage msg = {};
+  msg.payload = {0xCC, 0xCC, 0xCC, 0xCC};
+
+  for (auto const& [start, expectedPayload] : shifts) {
+    Signal s(start, 20);
+
+    can::V1_0::CanMessage expectedMsg = {};
+    expectedMsg.payload = expectedPayload;
+
+    can::V1_0::CanMessage editedMsg = msg;
+    s.set(editedMsg, 0xDEADB);
+
+    ASSERT_EQ(expectedMsg, editedMsg) << "shift of " << start << " failed";
+  }
+}
+
+}  // namespace android::hardware::automotive::protocan::unittest
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 1216d36..c33a2e7 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -653,7 +653,7 @@
         ASSERT_GT(height, 0);
 
         android::ui::DisplayState* pState = (android::ui::DisplayState*)state.data();
-        ASSERT_NE(pState->layerStack, -1);
+        ASSERT_NE(pState->layerStack, android::ui::INVALID_LAYER_STACK);
     });
 
     // Test each reported camera
diff --git a/automotive/occupant_awareness/aidl/Android.bp b/automotive/occupant_awareness/aidl/Android.bp
index 26c53fa..6ddc127 100644
--- a/automotive/occupant_awareness/aidl/Android.bp
+++ b/automotive/occupant_awareness/aidl/Android.bp
@@ -16,7 +16,12 @@
     stability: "vintf",
     backend: {
         java: {
-            platform_apis: true,
+            sdk_version: "module_current",
+            min_sdk_version: "31",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.car.framework",
+            ],
         },
         ndk: {
             vndk: {
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index e2164b1..5c2e0ea 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -21,4 +21,8 @@
         "android.hidl.base@1.0",
     ],
     gen_java: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.car.framework",
+    ],
 }
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index ba11a49..3cf41dc 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -47,6 +47,7 @@
 
 cc_library_headers {
     name: "vhal_v2_0_common_headers",
+    visibility: ["//visibility:public"],
     vendor: true,
     export_include_dirs: ["common/include/vhal_v2_0"],
 }
@@ -58,6 +59,7 @@
     defaults: ["vhal_v2_0_target_defaults"],
     srcs: [
         "common/src/Obd2SensorStore.cpp",
+        "common/src/ProtoMessageConverter.cpp",
         "common/src/SubscriptionManager.cpp",
         "common/src/VehicleHalManager.cpp",
         "common/src/VehicleObjectPool.cpp",
@@ -68,9 +70,13 @@
     ],
     shared_libs: [
         "libbase",
+        "libprotobuf-cpp-lite",
     ],
     local_include_dirs: ["common/include/vhal_v2_0"],
     export_include_dirs: ["common/include"],
+    static_libs: [
+        "android.hardware.automotive.vehicle@2.0-libproto-native",
+    ],
 }
 
 // Vehicle default VehicleHAL implementation
@@ -80,24 +86,18 @@
     defaults: ["vhal_v2_0_target_defaults"],
     cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
     srcs: [
-        "impl/vhal_v2_0/CommConn.cpp",
-        "impl/vhal_v2_0/EmulatedVehicleConnector.cpp",
-        "impl/vhal_v2_0/EmulatedVehicleHal.cpp",
+        "impl/vhal_v2_0/DefaultVehicleHal.cpp",
         "impl/vhal_v2_0/VehicleHalClient.cpp",
-        "impl/vhal_v2_0/VehicleHalServer.cpp",
-        "impl/vhal_v2_0/VehicleEmulator.cpp",
-        "impl/vhal_v2_0/PipeComm.cpp",
-        "impl/vhal_v2_0/ProtoMessageConverter.cpp",
-        "impl/vhal_v2_0/SocketComm.cpp",
+        "impl/vhal_v2_0/DefaultVehicleHalServer.cpp",
         "impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
         "impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
         "impl/vhal_v2_0/GeneratorHub.cpp",
-        "impl/vhal_v2_0/qemu_pipe.cpp",
+        "impl/vhal_v2_0/FakeObd2Frame.cpp",
     ],
     local_include_dirs: ["common/include/vhal_v2_0"],
     export_include_dirs: ["impl"],
     whole_static_libs: [
-        "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib",
+        "android.hardware.automotive.vehicle@2.0-fake-user-hal-lib",
         "android.hardware.automotive.vehicle@2.0-manager-lib",
     ],
     shared_libs: [
@@ -110,19 +110,6 @@
     ],
 }
 
-// Library used  to emulate User HAL behavior through lshal debug requests.
-cc_library_static {
-    name: "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib",
-    vendor: true,
-    defaults: ["vhal_v2_0_target_defaults"],
-    srcs: [
-        "impl/vhal_v2_0/EmulatedUserHal.cpp",
-    ],
-    whole_static_libs: [
-        "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
-    ],
-}
-
 // Vehicle HAL Server reference impl lib
 cc_library_static {
     name: "android.hardware.automotive.vehicle@2.0-server-common-lib",
@@ -133,10 +120,14 @@
     export_include_dirs: ["common/include"],
     srcs: [
         "common/src/Obd2SensorStore.cpp",
+        "common/src/ProtoMessageConverter.cpp",
         "common/src/VehicleObjectPool.cpp",
         "common/src/VehiclePropertyStore.cpp",
         "common/src/VehicleUtils.cpp",
     ],
+    static_libs: [
+        "android.hardware.automotive.vehicle@2.0-libproto-native",
+    ],
 }
 
 // Vehicle HAL Server default implementation
@@ -151,12 +142,11 @@
         "impl/vhal_v2_0/GeneratorHub.cpp",
         "impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
         "impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
-        "impl/vhal_v2_0/ProtoMessageConverter.cpp",
-        "impl/vhal_v2_0/VehicleHalServer.cpp",
+        "impl/vhal_v2_0/DefaultVehicleHalServer.cpp",
+        "impl/vhal_v2_0/FakeObd2Frame.cpp",
     ],
     whole_static_libs: [
         "android.hardware.automotive.vehicle@2.0-server-common-lib",
-        "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
     ],
     static_libs: [
         "android.hardware.automotive.vehicle@2.0-libproto-native",
@@ -184,6 +174,16 @@
         "libbase",
         "libcutils",
     ],
+    // Exclude share libraries from default because they might be missing on
+    // some test platforms and we are using static libraries instead.
+    exclude_shared_libs: [
+        "android.automotive.watchdog-V2-ndk",
+        "android.hardware.automotive.vehicle@2.0",
+    ],
+    static_libs: [
+        "android.automotive.watchdog-V2-ndk",
+        "android.hardware.automotive.vehicle@2.0",
+    ],
     header_libs: ["libbase_headers"],
     test_suites: ["general-tests"],
 }
@@ -194,22 +194,41 @@
     defaults: ["vhal_v2_0_target_defaults"],
     srcs: [
         "impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp",
+        "impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp",
     ],
     static_libs: [
+        "libbase",
+        "libcutils",
+        "libgmock",
+        "libjsoncpp",
+        "libprotobuf-cpp-lite",
+    ],
+    // Exclude share libraries from default because they might be missing on
+    // some test platforms and we are using static libraries instead.
+    exclude_shared_libs: [
+        "android.automotive.watchdog-V2-ndk",
+        "android.hardware.automotive.vehicle@2.0",
+    ],
+    whole_static_libs: [
+        "android.automotive.watchdog-V2-ndk",
+        "android.hardware.automotive.vehicle@2.0",
         "android.hardware.automotive.vehicle@2.0-default-impl-lib",
         "android.hardware.automotive.vehicle@2.0-libproto-native",
-        "libprotobuf-cpp-lite",
+    ],
+    data: [
+        ":vhal_test_json",
+        ":vhal_test_override_json",
     ],
     test_suites: ["general-tests"],
 }
 
 cc_binary {
-    name: "android.hardware.automotive.vehicle@2.0-service",
+    name: "android.hardware.automotive.vehicle@2.0-default-service",
     defaults: ["vhal_v2_0_target_defaults"],
     vintf_fragments: [
-        "android.hardware.automotive.vehicle@2.0-service.xml",
+        "android.hardware.automotive.vehicle@2.0-default-service.xml",
     ],
-    init_rc: ["android.hardware.automotive.vehicle@2.0-service.rc"],
+    init_rc: ["android.hardware.automotive.vehicle@2.0-default-service.rc"],
     vendor: true,
     relative_install_path: "hw",
     srcs: ["VehicleService.cpp"],
@@ -220,8 +239,8 @@
     ],
     static_libs: [
         "android.hardware.automotive.vehicle@2.0-manager-lib",
-        "android.hardware.automotive.vehicle@2.0-default-impl-lib",
         "android.hardware.automotive.vehicle@2.0-libproto-native",
+        "android.hardware.automotive.vehicle@2.0-default-impl-lib",
     ],
 }
 
diff --git a/automotive/vehicle/2.0/default/TEST_MAPPING b/automotive/vehicle/2.0/default/TEST_MAPPING
new file mode 100644
index 0000000..bb58700
--- /dev/null
+++ b/automotive/vehicle/2.0/default/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+      "name": "android.hardware.automotive.vehicle@2.0-manager-unit-tests"
+    },
+    {
+      "name": "android.hardware.automotive.vehicle@2.0-default-impl-unit-tests"
+    }
+  ]
+}
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 7e8deb6..12e15f9 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -14,42 +14,40 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "automotive.vehicle@2.0-service"
+#define LOG_TAG "automotive.vehicle@2.0-default-service"
 #include <android/log.h>
 #include <hidl/HidlTransportSupport.h>
 
 #include <iostream>
 
-#include <vhal_v2_0/EmulatedUserHal.h>
-#include <vhal_v2_0/EmulatedVehicleConnector.h>
-#include <vhal_v2_0/EmulatedVehicleHal.h>
+#include <vhal_v2_0/DefaultVehicleConnector.h>
+#include <vhal_v2_0/DefaultVehicleHal.h>
 #include <vhal_v2_0/VehicleHalManager.h>
 
-using namespace android;
-using namespace android::hardware;
-using namespace android::hardware::automotive::vehicle::V2_0;
+using ::android::hardware::automotive::vehicle::V2_0::VehicleHalManager;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropertyStore;
+using ::android::hardware::automotive::vehicle::V2_0::impl::DefaultVehicleConnector;
+using ::android::hardware::automotive::vehicle::V2_0::impl::DefaultVehicleHal;
 
 int main(int /* argc */, char* /* argv */ []) {
     auto store = std::make_unique<VehiclePropertyStore>();
-    auto connector = std::make_unique<impl::EmulatedVehicleConnector>();
-    auto userHal = connector->getEmulatedUserHal();
-    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);
-    auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
+    auto connector = std::make_unique<DefaultVehicleConnector>();
+    auto hal = std::make_unique<DefaultVehicleHal>(store.get(), connector.get());
     auto service = std::make_unique<VehicleHalManager>(hal.get());
     connector->setValuePool(hal->getValuePool());
 
-    configureRpcThreadpool(4, true /* callerWillJoin */);
+    android::hardware::configureRpcThreadpool(4, true /* callerWillJoin */);
 
     ALOGI("Registering as service...");
-    status_t status = service->registerAsService();
+    android::status_t status = service->registerAsService();
 
-    if (status != OK) {
+    if (status != android::OK) {
         ALOGE("Unable to register vehicle service (%d)", status);
         return 1;
     }
 
     ALOGI("Ready");
-    joinRpcThreadpool();
+    android::hardware::joinRpcThreadpool();
 
-    return 1;
+    return 0;
 }
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-default-service.rc b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-default-service.rc
new file mode 100644
index 0000000..8279af7
--- /dev/null
+++ b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-default-service.rc
@@ -0,0 +1,4 @@
+service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-default-service
+    class early_hal
+    user vehicle_network
+    group system inet
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.xml b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-default-service.xml
similarity index 100%
rename from automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.xml
rename to automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-default-service.xml
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
deleted file mode 100644
index 44f9134..0000000
--- a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
-    class early_hal
-    user vehicle_network
-    group system inet
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/ProtoMessageConverter.h
similarity index 100%
rename from automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.h
rename to automotive/vehicle/2.0/default/common/include/vhal_v2_0/ProtoMessageConverter.h
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
index 2908a55..345c356 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include <android/hardware/automotive/vehicle/2.0/types.h>
+#include <utils/Log.h>
 
 #include "VehicleClient.h"
 #include "VehicleServer.h"
@@ -72,7 +73,21 @@
     }
 
     bool dump(const hidl_handle& handle, const hidl_vec<hidl_string>& options) override {
-        return this->onDump(handle, options);
+        // Calls server's onDump function and print the dumped info to the handle.
+        std::vector<std::string> stdOptions;
+        for (size_t i = 0; i < options.size(); i++) {
+            stdOptions.push_back(options[i]);
+        }
+        IVehicleServer::DumpResult result = this->onDump(stdOptions);
+        int fd = handle->data[0];
+        if (fd < 0) {
+            ALOGW("Invalid fd from HIDL handle: %d", fd);
+            return false;
+        }
+        if (result.buffer.size() != 0) {
+            dprintf(fd, "[VehicleHalServer] Dumped info: %s\n", result.buffer.c_str());
+        }
+        return result.callerShouldDumpState;
     }
 
     // To be implemented:
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
index ba9799a..2c484e8 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
@@ -28,6 +28,16 @@
  */
 class IVehicleServer {
   public:
+    // The return structure for onDump function.
+    struct DumpResult {
+        // If callerShouldDumpState is true, caller would print the information in buffer and
+        // continue to dump its state, otherwise would just dump the buffer and skip its own
+        // dumping logic.
+        bool callerShouldDumpState;
+        // The dumped information for the caller to print.
+        std::string buffer;
+    };
+
     IVehicleServer() = default;
 
     IVehicleServer(const IVehicleServer&) = delete;
@@ -54,15 +64,9 @@
     // generated by car (ECU/fake generator/injected)
     virtual void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) = 0;
 
-    // TODO (chenhaosjtuacm): fix this since there are no HIDL in non-Android OS
-#ifdef __ANDROID__
     // Dump method forwarded from HIDL's debug()
     // If implemented, it must return whether the caller should dump its state.
-    virtual bool onDump(const hidl_handle& /* handle */,
-                        const hidl_vec<hidl_string>& /* options */) {
-        return true;
-    }
-#endif  // __ANDROID__
+    virtual DumpResult onDump(const std::vector<std::string>& options) = 0;
 };
 
 }  // namespace android::hardware::automotive::vehicle::V2_0
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.cpp b/automotive/vehicle/2.0/default/common/src/ProtoMessageConverter.cpp
similarity index 100%
rename from automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.cpp
rename to automotive/vehicle/2.0/default/common/src/ProtoMessageConverter.cpp
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp
deleted file mode 100644
index 136b2e0..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "CommConn"
-
-#include <thread>
-
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
-#include <log/log.h>
-
-#include "CommConn.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-void CommConn::start() {
-    mReadThread = std::make_unique<std::thread>(std::bind(&CommConn::readThread, this));
-}
-
-void CommConn::stop() {
-    if (mReadThread->joinable()) {
-        mReadThread->join();
-    }
-}
-
-void CommConn::sendMessage(vhal_proto::EmulatorMessage const& msg) {
-    int numBytes = msg.ByteSize();
-    std::vector<uint8_t> buffer(static_cast<size_t>(numBytes));
-    if (!msg.SerializeToArray(buffer.data(), numBytes)) {
-        ALOGE("%s: SerializeToString failed!", __func__);
-        return;
-    }
-
-    write(buffer);
-}
-
-void CommConn::readThread() {
-    std::vector<uint8_t> buffer;
-    while (isOpen()) {
-        buffer = read();
-        if (buffer.size() == 0) {
-            ALOGI("%s: Read returned empty message, exiting read loop.", __func__);
-            break;
-        }
-
-        vhal_proto::EmulatorMessage rxMsg;
-        if (rxMsg.ParseFromArray(buffer.data(), static_cast<int32_t>(buffer.size()))) {
-            vhal_proto::EmulatorMessage respMsg;
-            mMessageProcessor->processMessage(rxMsg, respMsg);
-
-            sendMessage(respMsg);
-        }
-    }
-}
-
-}  // namespace impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h
deleted file mode 100644
index 6d36da4..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h
+++ /dev/null
@@ -1,117 +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 android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_
-
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include "VehicleHalProto.pb.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-/**
- * MessageProcess is an interface implemented by VehicleEmulator to process messages received
- * over a CommConn.
- */
-class MessageProcessor {
-   public:
-    virtual ~MessageProcessor() = default;
-
-    /**
-     * Process a single message received over a CommConn. Populate the given respMsg with the reply
-     * message we should send.
-     */
-    virtual void processMessage(vhal_proto::EmulatorMessage const& rxMsg,
-                                vhal_proto::EmulatorMessage& respMsg) = 0;
-};
-
-/**
- * This is the interface that both PipeComm and SocketComm use to represent a connection. The
- * connection will listen for commands on a separate 'read' thread.
- */
-class CommConn {
-   public:
-    CommConn(MessageProcessor* messageProcessor) : mMessageProcessor(messageProcessor) {}
-
-    virtual ~CommConn() {}
-
-    /**
-     * Start the read thread reading messages from this connection.
-     */
-    virtual void start();
-
-    /**
-     * Closes a connection if it is open.
-     */
-    virtual void stop();
-
-    /**
-     * Returns true if the connection is open and available to send/receive.
-     */
-    virtual bool isOpen() = 0;
-
-    /**
-     * Blocking call to read data from the connection.
-     *
-     * @return std::vector<uint8_t> Serialized protobuf data received from emulator.  This will be
-     *              an empty vector if the connection was closed or some other error occurred.
-     */
-    virtual std::vector<uint8_t> read() = 0;
-
-    /**
-     * Transmits a string of data to the emulator.
-     *
-     * @param data Serialized protobuf data to transmit.
-     *
-     * @return int Number of bytes transmitted, or -1 if failed.
-     */
-    virtual int write(const std::vector<uint8_t>& data) = 0;
-
-    /**
-     * Serialized and send the given message to the other side.
-     */
-    void sendMessage(vhal_proto::EmulatorMessage const& msg);
-
-   protected:
-    std::unique_ptr<std::thread> mReadThread;
-    MessageProcessor* mMessageProcessor;
-
-    /**
-     * A thread that reads messages in a loop, and responds. You can stop this thread by calling
-     * stop().
-     */
-    void readThread();
-};
-
-}  // namespace impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 55617be..cfbbbd3 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -493,8 +493,12 @@
                     .changeMode = VehiclePropertyChangeMode::STATIC,
                     .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
          .initialValue = {.int32Values = {FAN_DIRECTION_FACE, FAN_DIRECTION_FLOOR,
-                                          FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR}}},
-
+                                          FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR,
+                                          FAN_DIRECTION_DEFROST,
+                                          FAN_DIRECTION_FACE | FAN_DIRECTION_DEFROST,
+                                          FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST,
+                                          FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST |
+                                                  FAN_DIRECTION_FACE}}},
         {.config = {.prop = toInt(VehicleProperty::HVAC_SEAT_VENTILATION),
                     .access = VehiclePropertyAccess::READ_WRITE,
                     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -642,46 +646,6 @@
          .initialValue = {.floatValues = {101.0f}}},
 
         {
-                .config =
-                        {
-                                .prop = kGenerateFakeDataControllingProperty,
-                                .access = VehiclePropertyAccess::WRITE,
-                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                                .configArray = {1, 0, 0, 2, 0, 0, 0, 0, 0},
-                        },
-        },
-
-        {
-                .config =
-                        {
-                                .prop = kSetIntPropertyFromVehicleForTest,
-                                .access = VehiclePropertyAccess::WRITE,
-                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                                .configArray = {0, 0, 0, 2, 1, 0, 0, 0, 0},
-                        },
-        },
-
-        {
-                .config =
-                        {
-                                .prop = kSetFloatPropertyFromVehicleForTest,
-                                .access = VehiclePropertyAccess::WRITE,
-                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                                .configArray = {0, 0, 1, 0, 1, 0, 1, 0, 0},
-                        },
-        },
-
-        {
-                .config =
-                        {
-                                .prop = kSetBooleanPropertyFromVehicleForTest,
-                                .access = VehiclePropertyAccess::WRITE,
-                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                                .configArray = {0, 1, 1, 0, 1, 0, 0, 0, 0},
-                        },
-        },
-
-        {
                 .config = {.prop = kMixedTypePropertyForTest,
                            .access = VehiclePropertyAccess::READ_WRITE,
                            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -1072,7 +1036,7 @@
                                 .access = VehiclePropertyAccess::READ,
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                         },
-                .initialValue = {.int32Values = {0 /* ClusterHome */, -1 /* ClusterNone */}},
+                .initialValue = {.int32Values = {0 /* ClusterHome */}},
         },
         {
                 .config =
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleConnector.h
new file mode 100644
index 0000000..c3affb0
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleConnector.h
@@ -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.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleConnector_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleConnector_H_
+
+#include <vhal_v2_0/VehicleConnector.h>
+
+#include "DefaultVehicleHalServer.h"
+#include "VehicleHalClient.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+class DefaultVehicleConnector
+    : public IPassThroughConnector<VehicleHalClient, DefaultVehicleHalServer> {
+  public:
+    DefaultVehicleConnector() = default;
+
+    void triggerSendAllValues() { this->sendAllValuesToClient(); }
+};
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleConnector_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
new file mode 100644
index 0000000..318e9dd
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "DefaultVehicleHal_v2_0"
+
+#include <android-base/chrono_utils.h>
+#include <assert.h>
+#include <stdio.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+#include <vhal_v2_0/RecurrentTimer.h>
+#include <unordered_set>
+
+#include "FakeObd2Frame.h"
+#include "PropertyUtils.h"
+#include "VehicleUtils.h"
+
+#include "DefaultVehicleHal.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+namespace {
+constexpr std::chrono::nanoseconds kHeartBeatIntervalNs = 3s;
+
+const VehicleAreaConfig* getAreaConfig(const VehiclePropValue& propValue,
+                                       const VehiclePropConfig* config) {
+    if (isGlobalProp(propValue.prop)) {
+        if (config->areaConfigs.size() == 0) {
+            return nullptr;
+        }
+        return &(config->areaConfigs[0]);
+    } else {
+        for (auto& c : config->areaConfigs) {
+            if (c.areaId == propValue.areaId) {
+                return &c;
+            }
+        }
+    }
+    return nullptr;
+}
+
+VehicleHal::VehiclePropValuePtr addTimestamp(VehicleHal::VehiclePropValuePtr v) {
+    if (v.get()) {
+        v->timestamp = elapsedRealtimeNano();
+    }
+    return v;
+}
+}  // namespace
+
+VehicleHal::VehiclePropValuePtr DefaultVehicleHal::createVhalHeartBeatProp() {
+    VehicleHal::VehiclePropValuePtr v = getValuePool()->obtainInt64(uptimeMillis());
+    v->prop = static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT);
+    v->areaId = 0;
+    v->status = VehiclePropertyStatus::AVAILABLE;
+    return v;
+}
+
+DefaultVehicleHal::DefaultVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
+    : mPropStore(propStore), mRecurrentTimer(getTimerAction()), mVehicleClient(client) {
+    initStaticConfig();
+    mVehicleClient->registerPropertyValueCallback(
+            [this](const VehiclePropValue& value, bool updateStatus) {
+                onPropertyValue(value, updateStatus);
+            });
+}
+
+VehicleHal::VehiclePropValuePtr DefaultVehicleHal::getUserHalProp(
+        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
+    auto propId = requestedPropValue.prop;
+    ALOGI("get(): getting value for prop %d from User HAL", propId);
+    const auto& ret = mFakeUserHal.onGetProperty(requestedPropValue);
+    VehicleHal::VehiclePropValuePtr v = nullptr;
+    if (!ret.ok()) {
+        ALOGE("get(): User HAL returned error: %s", ret.error().message().c_str());
+        *outStatus = StatusCode(ret.error().code());
+    } else {
+        auto value = ret.value().get();
+        if (value != nullptr) {
+            ALOGI("get(): User HAL returned value: %s", toString(*value).c_str());
+            v = getValuePool()->obtain(*value);
+            *outStatus = StatusCode::OK;
+        } else {
+            ALOGE("get(): User HAL returned null value");
+            *outStatus = StatusCode::INTERNAL_ERROR;
+        }
+    }
+    return addTimestamp(std::move(v));
+}
+
+VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(const VehiclePropValue& requestedPropValue,
+                                                       StatusCode* outStatus) {
+    auto propId = requestedPropValue.prop;
+    ALOGV("get(%d)", propId);
+
+    if (mFakeUserHal.isSupported(propId)) {
+        return getUserHalProp(requestedPropValue, outStatus);
+    }
+
+    VehiclePropValuePtr v = nullptr;
+    if (propId == OBD2_FREEZE_FRAME) {
+        v = getValuePool()->obtainComplex();
+        *outStatus = fillObd2FreezeFrame(mPropStore, requestedPropValue, v.get());
+        return addTimestamp(std::move(v));
+    }
+
+    if (propId == OBD2_FREEZE_FRAME_INFO) {
+        v = getValuePool()->obtainComplex();
+        *outStatus = fillObd2DtcInfo(mPropStore, v.get());
+        return addTimestamp(std::move(v));
+    }
+
+    auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
+    if (internalPropValue != nullptr) {
+        v = getValuePool()->obtain(*internalPropValue);
+    }
+
+    if (!v) {
+        *outStatus = StatusCode::INVALID_ARG;
+    } else if (v->status == VehiclePropertyStatus::AVAILABLE) {
+        *outStatus = StatusCode::OK;
+    } else {
+        *outStatus = StatusCode::TRY_AGAIN;
+    }
+    return addTimestamp(std::move(v));
+}
+
+std::vector<VehiclePropConfig> DefaultVehicleHal::listProperties() {
+    return mPropStore->getAllConfigs();
+}
+
+bool DefaultVehicleHal::dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+    int nativeFd = fd->data[0];
+    if (nativeFd < 0) {
+        ALOGW("Invalid fd from HIDL handle: %d", nativeFd);
+        return false;
+    }
+    if (options.size() > 0) {
+        if (options[0] == "--help") {
+            std::string buffer;
+            buffer += "Fake user hal usage:\n";
+            buffer += mFakeUserHal.showDumpHelp();
+            buffer += "\n";
+            buffer += "VHAL server debug usage:\n";
+            buffer += "--debughal: send debug command to VHAL server, see '--debughal --help'\n";
+            buffer += "\n";
+            dprintf(nativeFd, "%s", buffer.c_str());
+            return false;
+        } else if (options[0] == kUserHalDumpOption) {
+            dprintf(nativeFd, "%s", mFakeUserHal.dump("").c_str());
+            return false;
+        }
+    } else {
+        // No options, dump the fake user hal state first and then send command to VHAL server
+        // to dump its state.
+        std::string buffer;
+        buffer += "Fake user hal state:\n";
+        buffer += mFakeUserHal.dump("  ");
+        buffer += "\n";
+        dprintf(nativeFd, "%s", buffer.c_str());
+    }
+
+    return mVehicleClient->dump(fd, options);
+}
+
+StatusCode DefaultVehicleHal::checkPropValue(const VehiclePropValue& value,
+                                             const VehiclePropConfig* config) {
+    int32_t property = value.prop;
+    VehiclePropertyType type = getPropType(property);
+    switch (type) {
+        case VehiclePropertyType::BOOLEAN:
+        case VehiclePropertyType::INT32:
+            if (value.value.int32Values.size() != 1) {
+                return StatusCode::INVALID_ARG;
+            }
+            break;
+        case VehiclePropertyType::INT32_VEC:
+            if (value.value.int32Values.size() < 1) {
+                return StatusCode::INVALID_ARG;
+            }
+            break;
+        case VehiclePropertyType::INT64:
+            if (value.value.int64Values.size() != 1) {
+                return StatusCode::INVALID_ARG;
+            }
+            break;
+        case VehiclePropertyType::INT64_VEC:
+            if (value.value.int64Values.size() < 1) {
+                return StatusCode::INVALID_ARG;
+            }
+            break;
+        case VehiclePropertyType::FLOAT:
+            if (value.value.floatValues.size() != 1) {
+                return StatusCode::INVALID_ARG;
+            }
+            break;
+        case VehiclePropertyType::FLOAT_VEC:
+            if (value.value.floatValues.size() < 1) {
+                return StatusCode::INVALID_ARG;
+            }
+            break;
+        case VehiclePropertyType::BYTES:
+            // We allow setting an empty bytes array.
+            break;
+        case VehiclePropertyType::STRING:
+            // We allow setting an empty string.
+            break;
+        case VehiclePropertyType::MIXED:
+            if (getPropGroup(property) == VehiclePropertyGroup::VENDOR) {
+                // We only checks vendor mixed properties.
+                return checkVendorMixedPropValue(value, config);
+            }
+            break;
+        default:
+            ALOGW("Unknown property type: %d", type);
+            return StatusCode::INVALID_ARG;
+    }
+    return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::checkVendorMixedPropValue(const VehiclePropValue& value,
+                                                        const VehiclePropConfig* config) {
+    auto configArray = config->configArray;
+    // configArray[0], 1 indicates the property has a String value, we allow the string value to
+    // be empty.
+
+    size_t int32Count = 0;
+    // configArray[1], 1 indicates the property has a Boolean value.
+    if (configArray[1] == 1) {
+        int32Count++;
+    }
+    // configArray[2], 1 indicates the property has an Integer value.
+    if (configArray[2] == 1) {
+        int32Count++;
+    }
+    // configArray[3], the number indicates the size of Integer[] in the property.
+    int32Count += static_cast<size_t>(configArray[3]);
+    if (value.value.int32Values.size() != int32Count) {
+        return StatusCode::INVALID_ARG;
+    }
+
+    size_t int64Count = 0;
+    // configArray[4], 1 indicates the property has a Long value.
+    if (configArray[4] == 1) {
+        int64Count++;
+    }
+    // configArray[5], the number indicates the size of Long[] in the property.
+    int64Count += static_cast<size_t>(configArray[5]);
+    if (value.value.int64Values.size() != int64Count) {
+        return StatusCode::INVALID_ARG;
+    }
+
+    size_t floatCount = 0;
+    // configArray[6], 1 indicates the property has a Float value.
+    if (configArray[6] == 1) {
+        floatCount++;
+    }
+    // configArray[7], the number indicates the size of Float[] in the property.
+    floatCount += static_cast<size_t>(configArray[7]);
+    if (value.value.floatValues.size() != floatCount) {
+        return StatusCode::INVALID_ARG;
+    }
+
+    // configArray[8], the number indicates the size of byte[] in the property.
+    if (configArray[8] != 0 && value.value.bytes.size() != static_cast<size_t>(configArray[8])) {
+        return StatusCode::INVALID_ARG;
+    }
+    return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::checkValueRange(const VehiclePropValue& value,
+                                              const VehicleAreaConfig* areaConfig) {
+    if (areaConfig == nullptr) {
+        return StatusCode::OK;
+    }
+    int32_t property = value.prop;
+    VehiclePropertyType type = getPropType(property);
+    switch (type) {
+        case VehiclePropertyType::INT32:
+            if (areaConfig->minInt32Value == 0 && areaConfig->maxInt32Value == 0) {
+                break;
+            }
+            // We already checked this in checkPropValue.
+            assert(value.value.int32Values.size() > 0);
+            if (value.value.int32Values[0] < areaConfig->minInt32Value ||
+                value.value.int32Values[0] > areaConfig->maxInt32Value) {
+                return StatusCode::INVALID_ARG;
+            }
+            break;
+        case VehiclePropertyType::INT64:
+            if (areaConfig->minInt64Value == 0 && areaConfig->maxInt64Value == 0) {
+                break;
+            }
+            // We already checked this in checkPropValue.
+            assert(value.value.int64Values.size() > 0);
+            if (value.value.int64Values[0] < areaConfig->minInt64Value ||
+                value.value.int64Values[0] > areaConfig->maxInt64Value) {
+                return StatusCode::INVALID_ARG;
+            }
+            break;
+        case VehiclePropertyType::FLOAT:
+            if (areaConfig->minFloatValue == 0 && areaConfig->maxFloatValue == 0) {
+                break;
+            }
+            // We already checked this in checkPropValue.
+            assert(value.value.floatValues.size() > 0);
+            if (value.value.floatValues[0] < areaConfig->minFloatValue ||
+                value.value.floatValues[0] > areaConfig->maxFloatValue) {
+                return StatusCode::INVALID_ARG;
+            }
+            break;
+        default:
+            // We don't check the rest of property types. Additional logic needs to be added if
+            // required for real implementation. E.g., you might want to enforce the range
+            // checks on vector as well or you might want to check the range for mixed property.
+            break;
+    }
+    return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::setUserHalProp(const VehiclePropValue& propValue) {
+    ALOGI("onSetProperty(): property %d will be handled by UserHal", propValue.prop);
+
+    const auto& ret = mFakeUserHal.onSetProperty(propValue);
+    if (!ret.ok()) {
+        ALOGE("onSetProperty(): HAL returned error: %s", ret.error().message().c_str());
+        return StatusCode(ret.error().code());
+    }
+    auto updatedValue = ret.value().get();
+    if (updatedValue != nullptr) {
+        ALOGI("onSetProperty(): updating property returned by HAL: %s",
+              toString(*updatedValue).c_str());
+        onPropertyValue(*updatedValue, true);
+    }
+    return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
+    if (propValue.status != VehiclePropertyStatus::AVAILABLE) {
+        // Android side cannot set property status - this value is the
+        // purview of the HAL implementation to reflect the state of
+        // its underlying hardware
+        return StatusCode::INVALID_ARG;
+    }
+
+    if (mFakeUserHal.isSupported(propValue.prop)) {
+        return setUserHalProp(propValue);
+    }
+
+    std::unordered_set<int32_t> powerProps(std::begin(kHvacPowerProperties),
+                                           std::end(kHvacPowerProperties));
+    if (powerProps.count(propValue.prop)) {
+        auto hvacPowerOn = mPropStore->readValueOrNull(
+                toInt(VehicleProperty::HVAC_POWER_ON),
+                (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT |
+                 VehicleAreaSeat::ROW_2_LEFT | VehicleAreaSeat::ROW_2_CENTER |
+                 VehicleAreaSeat::ROW_2_RIGHT));
+
+        if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1 &&
+            hvacPowerOn->value.int32Values[0] == 0) {
+            return StatusCode::NOT_AVAILABLE;
+        }
+    }
+
+    if (propValue.prop == OBD2_FREEZE_FRAME_CLEAR) {
+        return clearObd2FreezeFrames(mPropStore, propValue);
+    }
+    if (propValue.prop == VEHICLE_MAP_SERVICE) {
+        // Placeholder for future implementation of VMS property in the default hal. For
+        // now, just returns OK; otherwise, hal clients crash with property not supported.
+        return StatusCode::OK;
+    }
+
+    int32_t property = propValue.prop;
+    const VehiclePropConfig* config = mPropStore->getConfigOrNull(property);
+    if (config == nullptr) {
+        ALOGW("no config for prop 0x%x", property);
+        return StatusCode::INVALID_ARG;
+    }
+    const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, config);
+    if (!isGlobalProp(property) && areaConfig == nullptr) {
+        // Ignore areaId for global property. For non global property, check whether areaId is
+        // allowed. areaId must appear in areaConfig.
+        ALOGW("invalid area ID: 0x%x for prop 0x%x, not listed in config", propValue.areaId,
+              property);
+        return StatusCode::INVALID_ARG;
+    }
+    auto status = checkPropValue(propValue, config);
+    if (status != StatusCode::OK) {
+        ALOGW("invalid property value: %s", toString(propValue).c_str());
+        return status;
+    }
+    status = checkValueRange(propValue, areaConfig);
+    if (status != StatusCode::OK) {
+        ALOGW("property value out of range: %s", toString(propValue).c_str());
+        return status;
+    }
+
+    auto currentPropValue = mPropStore->readValueOrNull(propValue);
+    if (currentPropValue && currentPropValue->status != VehiclePropertyStatus::AVAILABLE) {
+        // do not allow Android side to set() a disabled/error property
+        return StatusCode::NOT_AVAILABLE;
+    }
+
+    // Send the value to the vehicle server, the server will talk to the (real or emulated) car
+    return mVehicleClient->setProperty(propValue, /*updateStatus=*/false);
+}
+
+// Parse supported properties list and generate vector of property values to hold current values.
+void DefaultVehicleHal::onCreate() {
+    auto configs = mVehicleClient->getAllPropertyConfig();
+
+    for (const auto& cfg : configs) {
+        if (isDiagnosticProperty(cfg)) {
+            // do not write an initial empty value for the diagnostic properties
+            // as we will initialize those separately.
+            continue;
+        }
+
+        int32_t numAreas = isGlobalProp(cfg.prop) ? 1 : cfg.areaConfigs.size();
+
+        for (int i = 0; i < numAreas; i++) {
+            int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId;
+
+            // Create a separate instance for each individual zone
+            VehiclePropValue prop = {
+                    .areaId = curArea,
+                    .prop = cfg.prop,
+                    .status = VehiclePropertyStatus::UNAVAILABLE,
+            };
+            // Allow the initial values to set status.
+            mPropStore->writeValue(prop, /*updateStatus=*/true);
+        }
+    }
+
+    mVehicleClient->triggerSendAllValues();
+
+    initObd2LiveFrame(mPropStore, *mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
+    initObd2FreezeFrame(mPropStore, *mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
+
+    registerHeartBeatEvent();
+}
+
+DefaultVehicleHal::~DefaultVehicleHal() {
+    mRecurrentTimer.unregisterRecurrentEvent(static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT));
+}
+
+void DefaultVehicleHal::registerHeartBeatEvent() {
+    mRecurrentTimer.registerRecurrentEvent(kHeartBeatIntervalNs,
+                                           static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT));
+}
+
+VehicleHal::VehiclePropValuePtr DefaultVehicleHal::doInternalHealthCheck() {
+    VehicleHal::VehiclePropValuePtr v = nullptr;
+
+    // This is an example of very simple health checking. VHAL is considered healthy if we can read
+    // PERF_VEHICLE_SPEED. The more comprehensive health checking is required.
+    VehiclePropValue propValue = {
+            .prop = static_cast<int32_t>(VehicleProperty::PERF_VEHICLE_SPEED),
+    };
+    auto internalPropValue = mPropStore->readValueOrNull(propValue);
+    if (internalPropValue != nullptr) {
+        v = createVhalHeartBeatProp();
+    } else {
+        ALOGW("VHAL health check failed");
+    }
+    return v;
+}
+
+void DefaultVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
+    auto& pool = *getValuePool();
+
+    for (int32_t property : properties) {
+        VehiclePropValuePtr v;
+        if (isContinuousProperty(property)) {
+            auto internalPropValue = mPropStore->readValueOrNull(property);
+            if (internalPropValue != nullptr) {
+                v = pool.obtain(*internalPropValue);
+            }
+        } else if (property == static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT)) {
+            // VHAL_HEARTBEAT is not a continuous value, but it needs to be updated periodically.
+            // So, the update is done through onContinuousPropertyTimer.
+            v = doInternalHealthCheck();
+        } else {
+            ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
+            continue;
+        }
+
+        if (v.get()) {
+            v->timestamp = elapsedRealtimeNano();
+            doHalEvent(std::move(v));
+        }
+    }
+}
+
+RecurrentTimer::Action DefaultVehicleHal::getTimerAction() {
+    return [this](const std::vector<int32_t>& properties) {
+        onContinuousPropertyTimer(properties);
+    };
+}
+
+StatusCode DefaultVehicleHal::subscribe(int32_t property, float sampleRate) {
+    ALOGI("%s propId: 0x%x, sampleRate: %f", __func__, property, sampleRate);
+
+    if (!isContinuousProperty(property)) {
+        return StatusCode::INVALID_ARG;
+    }
+
+    // If the config does not exist, isContinuousProperty should return false.
+    const VehiclePropConfig* config = mPropStore->getConfigOrNull(property);
+    if (sampleRate < config->minSampleRate || sampleRate > config->maxSampleRate) {
+        ALOGW("sampleRate out of range");
+        return StatusCode::INVALID_ARG;
+    }
+
+    mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);
+    return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::unsubscribe(int32_t property) {
+    ALOGI("%s propId: 0x%x", __func__, property);
+    if (!isContinuousProperty(property)) {
+        return StatusCode::INVALID_ARG;
+    }
+    // If the event was not registered before, this would do nothing.
+    mRecurrentTimer.unregisterRecurrentEvent(property);
+    return StatusCode::OK;
+}
+
+bool DefaultVehicleHal::isContinuousProperty(int32_t propId) const {
+    const VehiclePropConfig* config = mPropStore->getConfigOrNull(propId);
+    if (config == nullptr) {
+        ALOGW("Config not found for property: 0x%x", propId);
+        return false;
+    }
+    return config->changeMode == VehiclePropertyChangeMode::CONTINUOUS;
+}
+
+void DefaultVehicleHal::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
+    VehiclePropValuePtr updatedPropValue = getValuePool()->obtain(value);
+
+    if (mPropStore->writeValue(*updatedPropValue, updateStatus)) {
+        doHalEvent(std::move(updatedPropValue));
+    }
+}
+
+void DefaultVehicleHal::initStaticConfig() {
+    auto configs = mVehicleClient->getAllPropertyConfig();
+    for (auto&& cfg : configs) {
+        VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
+
+        switch (cfg.prop) {
+            case OBD2_FREEZE_FRAME: {
+                // We use timestamp as token for OBD2_FREEZE_FRAME
+                tokenFunction = [](const VehiclePropValue& propValue) {
+                    return propValue.timestamp;
+                };
+                break;
+            }
+            default:
+                break;
+        }
+
+        mPropStore->registerProperty(cfg, tokenFunction);
+    }
+}
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
new file mode 100644
index 0000000..4d3036e
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
+
+#include <vhal_v2_0/RecurrentTimer.h>
+#include <vhal_v2_0/VehicleHal.h>
+#include <vhal_v2_0/VehiclePropertyStore.h>
+
+#include "FakeUserHal.h"
+#include "VehicleHalClient.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+/** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */
+class DefaultVehicleHal : public VehicleHal {
+  public:
+    DefaultVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client);
+    ~DefaultVehicleHal();
+
+    // Initialize VHAL. Should always call registerHeartBeatEvent() during onCreate.
+    void onCreate() override;
+    std::vector<VehiclePropConfig> listProperties() override;
+    VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
+                            StatusCode* outStatus) override;
+    StatusCode set(const VehiclePropValue& propValue) override;
+    StatusCode subscribe(int32_t property, float sampleRate) override;
+    StatusCode unsubscribe(int32_t property) override;
+    bool dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
+
+  protected:
+    constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
+        return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
+    }
+
+    VehiclePropertyStore* mPropStore;
+    RecurrentTimer mRecurrentTimer;
+    VehicleHalClient* mVehicleClient;
+    FakeUserHal mFakeUserHal;
+
+    // The callback that would be called when a property value is updated. This function could
+    // be extended to handle specific property update event.
+    virtual void onPropertyValue(const VehiclePropValue& value, bool updateStatus);
+    // Do an internal health check, vendor should add health check logic in this function.
+    virtual VehicleHal::VehiclePropValuePtr doInternalHealthCheck();
+
+    // The callback that would be called for every event generated by 'subscribe' or heartbeat.
+    // Properties contains a list of properties that need to be handled.
+    void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
+    // Initiate config for all properties, would be called during onCreate().
+    void initStaticConfig();
+    // Whether the property is a continuous property.
+    bool isContinuousProperty(int32_t propId) const;
+    // Returns a lambda that could be used in mRecurrentTimer.
+    RecurrentTimer::Action getTimerAction();
+    // Check whether a propValue is valid according to its type.
+    StatusCode checkPropValue(const VehiclePropValue& propValue, const VehiclePropConfig* config);
+    // Check whether the property value is within the range according to area config.
+    StatusCode checkValueRange(const VehiclePropValue& propValue,
+                               const VehicleAreaConfig* areaConfig);
+    // Register the heart beat event to be sent every 3s. This is required to inform watch dog that
+    // VHAL is alive. Subclasses should always calls this function during onCreate.
+    void registerHeartBeatEvent();
+    // Get a user HAL property.
+    VehiclePropValuePtr getUserHalProp(const VehiclePropValue& requestedPropValue,
+                                       StatusCode* outStatus);
+    // Set a user HAL property.
+    StatusCode setUserHalProp(const VehiclePropValue& propValue);
+    // Create a VHAL heart beat property.
+    VehicleHal::VehiclePropValuePtr createVhalHeartBeatProp();
+
+  private:
+    // Check whether a vendor mixed value property is valid according to its config array.
+    // See 'VehiclePropertyType' documentation in 'types.hal' for detail.
+    StatusCode checkVendorMixedPropValue(const VehiclePropValue& value,
+                                         const VehiclePropConfig* config);
+    // Read the override properties from a config file.
+    void getAllPropertiesOverride();
+};
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
new file mode 100644
index 0000000..4704917
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
@@ -0,0 +1,571 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "DefaultVehicleHalServer"
+
+#include <fstream>
+#include <regex>
+
+#include <android-base/format.h>
+#include <android-base/logging.h>
+#include <android-base/parsedouble.h>
+#include <android-base/parseint.h>
+#include <android-base/properties.h>
+#include <utils/SystemClock.h>
+
+#include "DefaultConfig.h"
+#include "FakeObd2Frame.h"
+#include "JsonFakeValueGenerator.h"
+#include "LinearFakeValueGenerator.h"
+
+#include "DefaultVehicleHalServer.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+namespace {
+const char* VENDOR_OVERRIDE_DIR = "/vendor/etc/vhaloverride/";
+}  // namespace
+
+void DefaultVehicleHalServer::storePropInitialValue(const ConfigDeclaration& config) {
+    VehiclePropConfig cfg = config.config;
+
+    // A global property will have only a single area
+    int32_t numAreas = isGlobalProp(cfg.prop) ? 1 : cfg.areaConfigs.size();
+
+    for (int i = 0; i < numAreas; i++) {
+        int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId;
+
+        // Create a separate instance for each individual zone
+        VehiclePropValue prop = {
+                .areaId = curArea,
+                .prop = cfg.prop,
+        };
+
+        if (config.initialAreaValues.empty()) {
+            prop.value = config.initialValue;
+        } else if (auto valueForAreaIt = config.initialAreaValues.find(curArea);
+                   valueForAreaIt != config.initialAreaValues.end()) {
+            prop.value = valueForAreaIt->second;
+        } else {
+            LOG(WARNING) << __func__ << " failed to get default value for"
+                         << " prop 0x" << std::hex << cfg.prop << " area 0x" << std::hex << curArea;
+            prop.status = VehiclePropertyStatus::UNAVAILABLE;
+        }
+
+        mServerSidePropStore.writeValue(prop, true);
+    }
+}
+
+DefaultVehicleHalServer::DefaultVehicleHalServer() {
+    for (auto& it : kVehicleProperties) {
+        VehiclePropConfig cfg = it.config;
+        mServerSidePropStore.registerProperty(cfg);
+        // Skip diagnostic properties since there is special logic to handle those.
+        if (isDiagnosticProperty(cfg)) {
+            continue;
+        }
+        storePropInitialValue(it);
+    }
+    maybeOverrideProperties(VENDOR_OVERRIDE_DIR);
+}
+
+void DefaultVehicleHalServer::sendAllValuesToClient() {
+    constexpr bool update_status = true;
+    auto values = mServerSidePropStore.readAllValues();
+    for (const auto& value : values) {
+        onPropertyValueFromCar(value, update_status);
+    }
+}
+
+GeneratorHub* DefaultVehicleHalServer::getGeneratorHub() {
+    return &mGeneratorHub;
+}
+
+VehiclePropValuePool* DefaultVehicleHalServer::getValuePool() const {
+    if (!mValuePool) {
+        LOG(WARNING) << __func__ << ": Value pool not set!";
+    }
+    return mValuePool;
+}
+
+void DefaultVehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
+    if (!valuePool) {
+        LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
+    }
+    mValuePool = valuePool;
+}
+
+void DefaultVehicleHalServer::onFakeValueGenerated(const VehiclePropValue& value) {
+    constexpr bool updateStatus = true;
+    LOG(DEBUG) << __func__ << ": " << toString(value);
+    auto updatedPropValue = getValuePool()->obtain(value);
+    if (updatedPropValue) {
+        updatedPropValue->timestamp = value.timestamp;
+        updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
+        mServerSidePropStore.writeValue(*updatedPropValue, updateStatus);
+        onPropertyValueFromCar(*updatedPropValue, updateStatus);
+    }
+}
+
+std::vector<VehiclePropConfig> DefaultVehicleHalServer::onGetAllPropertyConfig() const {
+    return mServerSidePropStore.getAllConfigs();
+}
+
+DefaultVehicleHalServer::VehiclePropValuePtr DefaultVehicleHalServer::createApPowerStateReq(
+        VehicleApPowerStateReq state, int32_t param) {
+    auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
+    req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
+    req->areaId = 0;
+    req->timestamp = elapsedRealtimeNano();
+    req->status = VehiclePropertyStatus::AVAILABLE;
+    req->value.int32Values[0] = toInt(state);
+    req->value.int32Values[1] = param;
+    return req;
+}
+
+DefaultVehicleHalServer::VehiclePropValuePtr DefaultVehicleHalServer::createHwInputKeyProp(
+        VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
+    auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
+    keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
+    keyEvent->areaId = 0;
+    keyEvent->timestamp = elapsedRealtimeNano();
+    keyEvent->status = VehiclePropertyStatus::AVAILABLE;
+    keyEvent->value.int32Values[0] = toInt(action);
+    keyEvent->value.int32Values[1] = keyCode;
+    keyEvent->value.int32Values[2] = targetDisplay;
+    return keyEvent;
+}
+
+StatusCode DefaultVehicleHalServer::onSetProperty(const VehiclePropValue& value,
+                                                  bool updateStatus) {
+    LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
+
+    // Some properties need to be treated non-trivially
+    switch (value.prop) {
+        case AP_POWER_STATE_REPORT:
+            switch (value.value.int32Values[0]) {
+                case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
+                case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
+                    // CPMS is in WAIT_FOR_VHAL state, simply move to ON
+                    // Send back to HAL
+                    // ALWAYS update status for generated property value
+                    onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
+                                           true /* updateStatus */);
+                    break;
+                case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
+                    // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
+                    // Send back to HAL
+                    // ALWAYS update status for generated property value
+                    onPropertyValueFromCar(
+                            *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
+                            true /* updateStatus */);
+                    break;
+                case toInt(VehicleApPowerStateReport::ON):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
+                    // Do nothing
+                    break;
+                default:
+                    // Unknown state
+                    break;
+            }
+            break;
+
+#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+        case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
+        case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
+        case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE):
+        case VENDOR_CLUSTER_SWITCH_UI:
+        case VENDOR_CLUSTER_DISPLAY_STATE: {
+            auto updatedPropValue = createVehiclePropValue(getPropType(value.prop), 0);
+            updatedPropValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK);
+            if (isSystemProperty(value.prop)) {
+                updatedPropValue->prop |= toInt(VehiclePropertyGroup::VENDOR);
+            } else {
+                updatedPropValue->prop |= toInt(VehiclePropertyGroup::SYSTEM);
+            }
+            updatedPropValue->value = value.value;
+            updatedPropValue->timestamp = elapsedRealtimeNano();
+            updatedPropValue->areaId = value.areaId;
+            onPropertyValueFromCar(*updatedPropValue, updateStatus);
+            return StatusCode::OK;
+        }
+#endif  // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+
+        default:
+            break;
+    }
+
+    // In the real vhal, the value will be sent to Car ECU.
+    // We just pretend it is done here and send back to HAL
+    auto updatedPropValue = getValuePool()->obtain(value);
+    updatedPropValue->timestamp = elapsedRealtimeNano();
+
+    mServerSidePropStore.writeValue(*updatedPropValue, updateStatus);
+    onPropertyValueFromCar(*updatedPropValue, updateStatus);
+    return StatusCode::OK;
+}
+
+IVehicleServer::DumpResult DefaultVehicleHalServer::onDump(
+        const std::vector<std::string>& options) {
+    DumpResult result;
+    if (options.size() == 0) {
+        // No options, dump all stored properties.
+        result.callerShouldDumpState = true;
+        result.buffer += "Server side properties: \n";
+        auto values = mServerSidePropStore.readAllValues();
+        size_t i = 0;
+        for (const auto& value : values) {
+            result.buffer += fmt::format("[{}]: {}\n", i, toString(value));
+            i++;
+        }
+        return result;
+    }
+    if (options[0] != "--debughal") {
+        // We only expect "debughal" command. This might be some commands that the caller knows
+        // about, so let caller handle it.
+        result.callerShouldDumpState = true;
+        return result;
+    }
+
+    return debugCommand(options);
+}
+
+IVehicleServer::DumpResult DefaultVehicleHalServer::debugCommand(
+        const std::vector<std::string>& options) {
+    DumpResult result;
+    // This is a debug command for the HAL, caller should not continue to dump state.
+    result.callerShouldDumpState = false;
+
+    if (options.size() < 2) {
+        result.buffer += "No command specified\n";
+        result.buffer += getHelpInfo();
+        return result;
+    }
+
+    std::string command = options[1];
+    if (command == "--help") {
+        result.buffer += getHelpInfo();
+        return result;
+    } else if (command == "--genfakedata") {
+        return genFakeDataCommand(options);
+    } else if (command == "--setint" || command == "--setfloat" || command == "--setbool") {
+        return setValueCommand(options);
+    }
+
+    result.buffer += "Unknown command: \"" + command + "\"\n";
+    result.buffer += getHelpInfo();
+    return result;
+}
+
+std::string DefaultVehicleHalServer::getHelpInfo() {
+    return "Help: \n"
+           "Generate Fake Data: \n"
+           "\tStart a linear generator: \n"
+           "\t--debughal --genfakedata --startlinear [propID(int32)] [middleValue(float)] "
+           "[currentValue(float)] [dispersion(float)] [increment(float)] [interval(int64)]\n"
+           "\tStop a linear generator: \n"
+           "\t--debughal --genfakedata --stoplinear [propID(int32)]\n"
+           "\tStart a json generator: \n"
+           "\t--debughal --genfakedata --startjson [jsonFilePath(string)] "
+           "[repetition(int32)(optional)]\n"
+           "\tStop a json generator: \n"
+           "\t--debughal --genfakedata --stopjson [jsonFilePath(string)]\n"
+           "\tGenerate key press: \n"
+           "\t--debughal --genfakedata --keypress [keyCode(int32)] [display[int32]]\n"
+           "\tSet a int property value: \n"
+           "\t--setint [propID(int32)] [value(int32)] [timestamp(int64)] "
+           "[areaID(int32)(optional)]\n"
+           "\tSet a boolean property value: \n"
+           "\t--setbool [propID(int32)] [value(\"true\"/\"false\")] [timestamp(int64)] "
+           "[areaID(int32)(optional)]\n"
+           "\tSet a float property value: \n"
+           "\t--setfloat [propID(int32)] [value(float)] [timestamp(int64)] "
+           "[areaID(int32)(optional)]\n";
+}
+
+IVehicleServer::DumpResult DefaultVehicleHalServer::genFakeDataCommand(
+        const std::vector<std::string>& options) {
+    DumpResult result;
+    // This is a debug command for the HAL, caller should not continue to dump state.
+    result.callerShouldDumpState = false;
+
+    if (options.size() < 3) {
+        result.buffer += "No subcommand specified for genfakedata\n";
+        result.buffer += getHelpInfo();
+        return result;
+    }
+
+    std::string command = options[2];
+    if (command == "--startlinear") {
+        LOG(INFO) << __func__ << "FakeDataCommand::StartLinear";
+        // --debughal --genfakedata --startlinear [propID(int32)] [middleValue(float)]
+        // [currentValue(float)] [dispersion(float)] [increment(float)] [interval(int64)]
+        if (options.size() != 9) {
+            result.buffer +=
+                    "incorrect argument count, need 9 arguments for --genfakedata --startlinear\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        int32_t propId;
+        float middleValue;
+        float currentValue;
+        float dispersion;
+        float increment;
+        int64_t interval;
+        if (!android::base::ParseInt(options[3], &propId)) {
+            result.buffer += "failed to parse propdID as int: \"" + options[3] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        if (!android::base::ParseFloat(options[4], &middleValue)) {
+            result.buffer += "failed to parse middleValue as float: \"" + options[4] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        if (!android::base::ParseFloat(options[5], &currentValue)) {
+            result.buffer += "failed to parse currentValue as float: \"" + options[5] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        if (!android::base::ParseFloat(options[6], &dispersion)) {
+            result.buffer += "failed to parse dispersion as float: \"" + options[6] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        if (!android::base::ParseFloat(options[7], &increment)) {
+            result.buffer += "failed to parse increment as float: \"" + options[7] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        if (!android::base::ParseInt(options[8], &interval)) {
+            result.buffer += "failed to parse interval as int: \"" + options[8] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        auto generator = std::make_unique<LinearFakeValueGenerator>(
+                propId, middleValue, currentValue, dispersion, increment, interval);
+        getGeneratorHub()->registerGenerator(propId, std::move(generator));
+        return result;
+    } else if (command == "--stoplinear") {
+        LOG(INFO) << __func__ << "FakeDataCommand::StopLinear";
+        // --debughal --genfakedata --stoplinear [propID(int32)]
+        if (options.size() != 4) {
+            result.buffer +=
+                    "incorrect argument count, need 4 arguments for --genfakedata --stoplinear\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        int32_t propId;
+        if (!android::base::ParseInt(options[3], &propId)) {
+            result.buffer += "failed to parse propdID as int: \"" + options[3] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        getGeneratorHub()->unregisterGenerator(propId);
+        return result;
+    } else if (command == "--startjson") {
+        LOG(INFO) << __func__ << "FakeDataCommand::StartJson";
+        // --debughal --genfakedata --startjson [jsonFilePath(string)] [repetition(int32)(optional)]
+        if (options.size() != 4 && options.size() != 5) {
+            result.buffer +=
+                    "incorrect argument count, need 4 or 5 arguments for --genfakedata "
+                    "--startjson\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        std::string fileName = options[3];
+        int32_t cookie = std::hash<std::string>()(fileName);
+        // Iterate infinitely if repetition number is not provided
+        int32_t repetition = -1;
+        if (options.size() == 5) {
+            if (!android::base::ParseInt(options[4], &repetition)) {
+                result.buffer += "failed to parse repetition as int: \"" + options[4] + "\"\n";
+                result.buffer += getHelpInfo();
+                return result;
+            }
+        }
+        auto generator = std::make_unique<JsonFakeValueGenerator>(fileName, repetition);
+        if (!generator->hasNext()) {
+            result.buffer += "invalid JSON file, no events";
+            return result;
+        }
+        getGeneratorHub()->registerGenerator(cookie, std::move(generator));
+        return result;
+    } else if (command == "--stopjson") {
+        LOG(INFO) << __func__ << "FakeDataCommand::StopJson";
+        // --debughal --genfakedata --stopjson [jsonFilePath(string)]
+        if (options.size() != 4) {
+            result.buffer +=
+                    "incorrect argument count, need 4 arguments for --genfakedata --stopjson\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        std::string fileName = options[3];
+        int32_t cookie = std::hash<std::string>()(fileName);
+        getGeneratorHub()->unregisterGenerator(cookie);
+        return result;
+    } else if (command == "--keypress") {
+        LOG(INFO) << __func__ << "FakeDataCommand::KeyPress";
+        int32_t keyCode;
+        int32_t display;
+        // --debughal --genfakedata --keypress [keyCode(int32)] [display[int32]]
+        if (options.size() != 5) {
+            result.buffer +=
+                    "incorrect argument count, need 5 arguments for --genfakedata --keypress\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        if (!android::base::ParseInt(options[3], &keyCode)) {
+            result.buffer += "failed to parse keyCode as int: \"" + options[3] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        if (!android::base::ParseInt(options[4], &display)) {
+            result.buffer += "failed to parse display as int: \"" + options[4] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        // Send back to HAL
+        onPropertyValueFromCar(
+                *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
+                /*updateStatus=*/true);
+        onPropertyValueFromCar(
+                *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
+                /*updateStatus=*/true);
+        return result;
+    }
+
+    result.buffer += "Unknown command: \"" + command + "\"\n";
+    result.buffer += getHelpInfo();
+    return result;
+}
+
+void DefaultVehicleHalServer::maybeOverrideProperties(const char* overrideDir) {
+    if (android::base::GetBoolProperty("persist.vendor.vhal_init_value_override", false)) {
+        overrideProperties(overrideDir);
+    }
+}
+
+void DefaultVehicleHalServer::overrideProperties(const char* overrideDir) {
+    LOG(INFO) << "loading vendor override properties from " << overrideDir;
+    if (auto dir = opendir(overrideDir)) {
+        std::regex reg_json(".*[.]json", std::regex::icase);
+        while (auto f = readdir(dir)) {
+            if (!regex_match(f->d_name, reg_json)) {
+                continue;
+            }
+            std::string file = overrideDir + std::string(f->d_name);
+            JsonFakeValueGenerator tmpGenerator(file);
+
+            std::vector<VehiclePropValue> propValues = tmpGenerator.getAllEvents();
+            for (const VehiclePropValue& prop : propValues) {
+                mServerSidePropStore.writeValue(prop, true);
+            }
+        }
+        closedir(dir);
+    }
+}
+
+IVehicleServer::DumpResult DefaultVehicleHalServer::setValueCommand(
+        const std::vector<std::string>& options) {
+    DumpResult result;
+    // This is a debug command for the HAL, caller should not continue to dump state.
+    result.callerShouldDumpState = false;
+    // --debughal --set* [propID(int32)] [value] [timestamp(int64)]
+    // [areaId(int32)(optional)]
+    if (options.size() != 5 && options.size() != 6) {
+        result.buffer +=
+                "incorrect argument count, need 5 or 6 arguments for --setint or --setfloat or "
+                "--setbool\n";
+        result.buffer += getHelpInfo();
+        return result;
+    }
+    std::unique_ptr<VehiclePropValue> updatedPropValue;
+    int32_t propId;
+    int32_t intValue;
+    float floatValue;
+    int64_t timestamp;
+    int32_t areaId = 0;
+    if (options[1] == "--setint") {
+        updatedPropValue = std::move(createVehiclePropValue(VehiclePropertyType::INT32, 1));
+        if (!android::base::ParseInt(options[3], &intValue)) {
+            result.buffer += "failed to parse value as int: \"" + options[3] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        updatedPropValue->value.int32Values[0] = intValue;
+    } else if (options[1] == "--setbool") {
+        updatedPropValue = std::move(createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1));
+        if (options[3] == "true" || options[3] == "True") {
+            updatedPropValue->value.int32Values[0] = 1;
+        } else if (options[3] == "false" || options[3] == "False") {
+            updatedPropValue->value.int32Values[0] = 0;
+        } else {
+            result.buffer += "failed to parse value as bool, only accepts true/false: \"" +
+                             options[3] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+    } else {
+        updatedPropValue = std::move(createVehiclePropValue(VehiclePropertyType::FLOAT, 1));
+        if (!android::base::ParseFloat(options[3], &floatValue)) {
+            result.buffer += "failed to parse value as float: \"" + options[3] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+        updatedPropValue->value.floatValues[0] = floatValue;
+    }
+    if (!android::base::ParseInt(options[2], &propId)) {
+        result.buffer += "failed to parse propID as int: \"" + options[2] + "\"\n";
+        result.buffer += getHelpInfo();
+        return result;
+    }
+    updatedPropValue->prop = propId;
+    if (!android::base::ParseInt(options[4], &timestamp)) {
+        result.buffer += "failed to parse timestamp as int: \"" + options[4] + "\"\n";
+        result.buffer += getHelpInfo();
+        return result;
+    }
+    updatedPropValue->timestamp = timestamp;
+    if (options.size() == 6) {
+        if (!android::base::ParseInt(options[5], &areaId)) {
+            result.buffer += "failed to parse areaID as int: \"" + options[5] + "\"\n";
+            result.buffer += getHelpInfo();
+            return result;
+        }
+    }
+    updatedPropValue->areaId = areaId;
+
+    onPropertyValueFromCar(*updatedPropValue, /*updateStatus=*/true);
+    return result;
+}
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.h
new file mode 100644
index 0000000..8754846
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <vhal_v2_0/VehicleObjectPool.h>
+#include <vhal_v2_0/VehiclePropertyStore.h>
+#include <vhal_v2_0/VehicleServer.h>
+
+#include "DefaultConfig.h"
+#include "GeneratorHub.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+// This contains the server operation for VHAL running in emulator.
+class DefaultVehicleHalServer : public IVehicleServer {
+  public:
+    DefaultVehicleHalServer();
+
+    // Send all the property values to client.
+    void sendAllValuesToClient();
+
+    // Methods from IVehicleServer
+
+    std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;
+
+    StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
+
+    // Dump/debug the Default VHAL server. If options is empty, the internal information for the
+    // server would be dumped. Otherwise, the options would be treated as debug commands and sent
+    // to debug function to handle the commands.
+    DumpResult onDump(const std::vector<std::string>& options) override;
+
+    // Set the Property Value Pool used in this server
+    void setValuePool(VehiclePropValuePool* valuePool);
+
+  protected:
+    using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
+    GeneratorHub* getGeneratorHub();
+
+    VehiclePropValuePool* getValuePool() const;
+
+    void onFakeValueGenerated(const VehiclePropValue& value);
+
+    StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
+
+    VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
+
+    VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
+                                             int32_t targetDisplay);
+
+    void storePropInitialValue(const ConfigDeclaration& config);
+
+    // Handles debug commands. The first option must be "--debughal" otherwise the command would be
+    // ignored. The second option specifies the operations to execute. Different operations require
+    // different input options, for detail, see the helpInfo printed by getHelpInfo().
+    DumpResult debugCommand(const std::vector<std::string>& options);
+
+    // Gets help info. Contains the usage for different debug commands.
+    std::string getHelpInfo();
+
+    // If "persist.vendor.vhal_init_value_override" is true, try to override the properties default
+    // values according to JSON files in 'overrideDir'. Would be called in constructor using
+    // VENDOR_OVERRIDE_DIR as overrideDir.
+    void maybeOverrideProperties(const char* overrideDir);
+
+    // Handles "--genfakedata" debug command.
+    DumpResult genFakeDataCommand(const std::vector<std::string>& options);
+
+    // Handles "--setint" or "--setfloat" or "--setbool" debug command.
+    DumpResult setValueCommand(const std::vector<std::string>& options);
+
+  protected:
+    GeneratorHub mGeneratorHub{
+            [this](const VehiclePropValue& value) { return onFakeValueGenerated(value); }};
+
+    VehiclePropValuePool* mValuePool{nullptr};
+    VehiclePropertyStore mServerSidePropStore;
+
+  private:
+    // Expose protected methods to unit test.
+    friend class DefaultVhalImplTestHelper;
+    // Override the properties using config files in 'overrideDir'.
+    void overrideProperties(const char* overrideDir);
+};
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
deleted file mode 100644
index 3bdf5a8..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
+++ /dev/null
@@ -1,351 +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.
- */
-#define LOG_TAG "EmulatedUserHal"
-
-#include "EmulatedUserHal.h"
-
-#include <cutils/log.h>
-#include <utils/SystemClock.h>
-
-#include "UserHalHelper.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-namespace {
-
-using android::base::Error;
-using android::base::Result;
-
-constexpr int32_t INITIAL_USER_INFO = static_cast<int32_t>(VehicleProperty::INITIAL_USER_INFO);
-constexpr int32_t SWITCH_USER = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
-constexpr int32_t CREATE_USER = static_cast<int32_t>(VehicleProperty::CREATE_USER);
-constexpr int32_t REMOVE_USER = static_cast<int32_t>(VehicleProperty::REMOVE_USER);
-constexpr int32_t USER_IDENTIFICATION_ASSOCIATION =
-        static_cast<int32_t>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
-
-Result<int32_t> getRequestId(const VehiclePropValue& value) {
-    if (value.value.int32Values.size() < 1) {
-        return Error(static_cast<int>(StatusCode::INVALID_ARG))
-               << "no int32values on " << toString(value);
-    }
-    return value.value.int32Values[0];
-}
-
-Result<SwitchUserMessageType> getSwitchUserMessageType(const VehiclePropValue& value) {
-    if (value.value.int32Values.size() < 2) {
-        return Error(static_cast<int>(StatusCode::INVALID_ARG))
-               << "missing switch user message type " << toString(value);
-    }
-    return user_hal_helper::verifyAndCast<SwitchUserMessageType>(value.value.int32Values[1]);
-}
-
-}  // namespace
-
-bool EmulatedUserHal::isSupported(int32_t prop) {
-    switch (prop) {
-        case INITIAL_USER_INFO:
-        case SWITCH_USER:
-        case CREATE_USER:
-        case REMOVE_USER:
-        case USER_IDENTIFICATION_ASSOCIATION:
-            return true;
-        default:
-            return false;
-    }
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetProperty(
-        const VehiclePropValue& value) {
-    ALOGV("onSetProperty(): %s", toString(value).c_str());
-
-    switch (value.prop) {
-        case INITIAL_USER_INFO:
-            return onSetInitialUserInfoResponse(value);
-        case SWITCH_USER:
-            return onSetSwitchUserResponse(value);
-        case CREATE_USER:
-            return onSetCreateUserResponse(value);
-        case REMOVE_USER:
-            ALOGI("REMOVE_USER is FYI only, nothing to do...");
-            return {};
-        case USER_IDENTIFICATION_ASSOCIATION:
-            return onSetUserIdentificationAssociation(value);
-        default:
-            return Error(static_cast<int>(StatusCode::INVALID_ARG))
-                   << "Unsupported property: " << toString(value);
-    }
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onGetProperty(
-        const VehiclePropValue& value) {
-    ALOGV("onGetProperty(%s)", toString(value).c_str());
-    switch (value.prop) {
-        case INITIAL_USER_INFO:
-        case SWITCH_USER:
-        case CREATE_USER:
-        case REMOVE_USER:
-            ALOGE("onGetProperty(): %d is only supported on SET", value.prop);
-            return Error(static_cast<int>(StatusCode::INVALID_ARG)) << "only supported on SET";
-        case USER_IDENTIFICATION_ASSOCIATION:
-            return onGetUserIdentificationAssociation(value);
-        default:
-            ALOGE("onGetProperty(): %d is not supported", value.prop);
-            return Error(static_cast<int>(StatusCode::INVALID_ARG)) << "not supported by User HAL";
-    }
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onGetUserIdentificationAssociation(
-        const VehiclePropValue& value) {
-    if (mSetUserIdentificationAssociationResponseFromCmd == nullptr) {
-        return defaultUserIdentificationAssociation(value);
-    }
-    ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s",
-          toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
-    auto newValue = std::unique_ptr<VehiclePropValue>(
-            new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
-    auto requestId = getRequestId(value);
-    if (requestId.ok()) {
-        // Must use the same requestId
-        newValue->value.int32Values[0] = *requestId;
-    } else {
-        ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s", toString(value).c_str());
-    }
-    return newValue;
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetInitialUserInfoResponse(
-        const VehiclePropValue& value) {
-    auto requestId = getRequestId(value);
-    if (!requestId.ok()) {
-        ALOGE("Failed to get requestId on set(INITIAL_USER_INFO): %s",
-              requestId.error().message().c_str());
-        return requestId.error();
-    }
-
-    if (value.areaId != 0) {
-        ALOGD("set(INITIAL_USER_INFO) called from lshal; storing it: %s", toString(value).c_str());
-        mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
-        return {};
-    }
-
-    ALOGD("set(INITIAL_USER_INFO) called from Android: %s", toString(value).c_str());
-    if (mInitialUserResponseFromCmd != nullptr) {
-        ALOGI("replying INITIAL_USER_INFO with lshal value:  %s",
-              toString(*mInitialUserResponseFromCmd).c_str());
-        return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), *requestId);
-    }
-
-    // Returns default response
-    auto updatedValue = user_hal_helper::toVehiclePropValue(InitialUserInfoResponse{
-            .requestId = *requestId,
-            .action = InitialUserInfoResponseAction::DEFAULT,
-    });
-    ALOGI("no lshal response; replying with InitialUserInfoResponseAction::DEFAULT: %s",
-          toString(*updatedValue).c_str());
-    return updatedValue;
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetSwitchUserResponse(
-        const VehiclePropValue& value) {
-    auto requestId = getRequestId(value);
-    if (!requestId.ok()) {
-        ALOGE("Failed to get requestId on set(SWITCH_USER): %s",
-              requestId.error().message().c_str());
-        return requestId.error();
-    }
-
-    auto messageType = getSwitchUserMessageType(value);
-    if (!messageType.ok()) {
-        ALOGE("Failed to get messageType on set(SWITCH_USER): %s",
-              messageType.error().message().c_str());
-        return messageType.error();
-    }
-
-    if (value.areaId != 0) {
-        if (*messageType == SwitchUserMessageType::VEHICLE_REQUEST) {
-            // User HAL can also request a user switch, so we need to check it first
-            ALOGD("set(SWITCH_USER) called from lshal to emulate a vehicle request: %s",
-                  toString(value).c_str());
-            return std::unique_ptr<VehiclePropValue>(new VehiclePropValue(value));
-        }
-        // Otherwise, we store it
-        ALOGD("set(SWITCH_USER) called from lshal; storing it: %s", toString(value).c_str());
-        mSwitchUserResponseFromCmd.reset(new VehiclePropValue(value));
-        return {};
-    }
-    ALOGD("set(SWITCH_USER) called from Android: %s", toString(value).c_str());
-
-    if (mSwitchUserResponseFromCmd != nullptr) {
-        ALOGI("replying SWITCH_USER with lshal value:  %s",
-              toString(*mSwitchUserResponseFromCmd).c_str());
-        return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), *requestId);
-    }
-
-    if (*messageType == SwitchUserMessageType::LEGACY_ANDROID_SWITCH ||
-        *messageType == SwitchUserMessageType::ANDROID_POST_SWITCH) {
-        ALOGI("request is %s; ignoring it", toString(*messageType).c_str());
-        return {};
-    }
-
-    // Returns default response
-    auto updatedValue = user_hal_helper::toVehiclePropValue(SwitchUserResponse{
-            .requestId = *requestId,
-            .messageType = SwitchUserMessageType::VEHICLE_RESPONSE,
-            .status = SwitchUserStatus::SUCCESS,
-    });
-    ALOGI("no lshal response; replying with VEHICLE_RESPONSE / SUCCESS: %s",
-          toString(*updatedValue).c_str());
-    return updatedValue;
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetCreateUserResponse(
-        const VehiclePropValue& value) {
-    auto requestId = getRequestId(value);
-    if (!requestId.ok()) {
-        ALOGE("Failed to get requestId on set(CREATE_USER): %s",
-              requestId.error().message().c_str());
-        return requestId.error();
-    }
-
-    if (value.areaId != 0) {
-        ALOGD("set(CREATE_USER) called from lshal; storing it: %s", toString(value).c_str());
-        mCreateUserResponseFromCmd.reset(new VehiclePropValue(value));
-        return {};
-    }
-    ALOGD("set(CREATE_USER) called from Android: %s", toString(value).c_str());
-
-    if (mCreateUserResponseFromCmd != nullptr) {
-        ALOGI("replying CREATE_USER with lshal value:  %s",
-              toString(*mCreateUserResponseFromCmd).c_str());
-        return sendUserHalResponse(std::move(mCreateUserResponseFromCmd), *requestId);
-    }
-
-    // Returns default response
-    auto updatedValue = user_hal_helper::toVehiclePropValue(CreateUserResponse{
-            .requestId = *requestId,
-            .status = CreateUserStatus::SUCCESS,
-    });
-    ALOGI("no lshal response; replying with SUCCESS: %s", toString(*updatedValue).c_str());
-    return updatedValue;
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetUserIdentificationAssociation(
-        const VehiclePropValue& value) {
-    auto requestId = getRequestId(value);
-    if (!requestId.ok()) {
-        ALOGE("Failed to get requestId on set(USER_IDENTIFICATION_ASSOCIATION): %s",
-              requestId.error().message().c_str());
-        return requestId.error();
-    }
-
-    if (value.areaId != 0) {
-        ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from lshal; storing it: %s",
-              toString(value).c_str());
-        mSetUserIdentificationAssociationResponseFromCmd.reset(new VehiclePropValue(value));
-        return {};
-    }
-    ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from Android: %s", toString(value).c_str());
-
-    if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
-        ALOGI("replying USER_IDENTIFICATION_ASSOCIATION with lshal value:  %s",
-              toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
-        // Not moving response so it can be used on GET requests
-        auto copy = std::unique_ptr<VehiclePropValue>(
-                new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
-        return sendUserHalResponse(std::move(copy), *requestId);
-    }
-    // Returns default response
-    return defaultUserIdentificationAssociation(value);
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::defaultUserIdentificationAssociation(
-        const VehiclePropValue& request) {
-    // TODO(b/159498909): return a response with NOT_ASSOCIATED_ANY_USER for all requested types
-    ALOGE("no lshal response for %s; replying with NOT_AVAILABLE", toString(request).c_str());
-    return Error(static_cast<int>(StatusCode::NOT_AVAILABLE)) << "not set by lshal";
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse(
-        std::unique_ptr<VehiclePropValue> response, int32_t requestId) {
-    switch (response->areaId) {
-        case 1:
-            ALOGD("returning response with right request id");
-            response->value.int32Values[0] = requestId;
-            break;
-        case 2:
-            ALOGD("returning response with wrong request id");
-            response->value.int32Values[0] = -requestId;
-            break;
-        case 3:
-            ALOGD("not generating a property change event because of lshal prop: %s",
-                  toString(*response).c_str());
-            return Error(static_cast<int>(StatusCode::NOT_AVAILABLE))
-                   << "not generating a property change event because of lshal prop: "
-                   << toString(*response);
-        default:
-            ALOGE("invalid action on lshal response: %s", toString(*response).c_str());
-            return Error(static_cast<int>(StatusCode::INTERNAL_ERROR))
-                   << "invalid action on lshal response: " << toString(*response);
-    }
-
-    ALOGD("updating property to: %s", toString(*response).c_str());
-    return response;
-}
-
-void EmulatedUserHal::showDumpHelp(int fd) {
-    dprintf(fd, "%s: dumps state used for user management\n", kUserHalDumpOption);
-}
-
-void EmulatedUserHal::dump(int fd, std::string indent) {
-    if (mInitialUserResponseFromCmd != nullptr) {
-        dprintf(fd, "%sInitialUserInfo response: %s\n", indent.c_str(),
-                toString(*mInitialUserResponseFromCmd).c_str());
-    } else {
-        dprintf(fd, "%sNo InitialUserInfo response\n", indent.c_str());
-    }
-    if (mSwitchUserResponseFromCmd != nullptr) {
-        dprintf(fd, "%sSwitchUser response: %s\n", indent.c_str(),
-                toString(*mSwitchUserResponseFromCmd).c_str());
-    } else {
-        dprintf(fd, "%sNo SwitchUser response\n", indent.c_str());
-    }
-    if (mCreateUserResponseFromCmd != nullptr) {
-        dprintf(fd, "%sCreateUser response: %s\n", indent.c_str(),
-                toString(*mCreateUserResponseFromCmd).c_str());
-    } else {
-        dprintf(fd, "%sNo CreateUser response\n", indent.c_str());
-    }
-    if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
-        dprintf(fd, "%sSetUserIdentificationAssociation response: %s\n", indent.c_str(),
-                toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
-    } else {
-        dprintf(fd, "%sNo SetUserIdentificationAssociation response\n", indent.c_str());
-    }
-}
-
-}  // namespace impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
deleted file mode 100644
index db2f117..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_
-
-#include <android-base/result.h>
-
-#include <android/hardware/automotive/vehicle/2.0/types.h>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-constexpr char kUserHalDumpOption[] = "--user-hal";
-
-/**
- * Class used to emulate User HAL behavior through lshal debug requests.
- */
-class EmulatedUserHal {
-  public:
-    EmulatedUserHal() {}
-
-    ~EmulatedUserHal() = default;
-
-    /**
-     * Checks if the emulator can handle the property.
-     */
-    bool isSupported(int32_t prop);
-
-    /**
-     * Lets the emulator set the property.
-     *
-     * @return updated property and StatusCode
-     */
-    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetProperty(
-            const VehiclePropValue& value);
-
-    /**
-     * Gets the property value from the emulator.
-     *
-     * @return property value and StatusCode
-     */
-    android::base::Result<std::unique_ptr<VehiclePropValue>> onGetProperty(
-            const VehiclePropValue& value);
-
-    /**
-     * Shows the User HAL emulation help.
-     */
-    void showDumpHelp(int fd);
-
-    /**
-     * Dump its contents.
-     */
-    void dump(int fd, std::string indent);
-
-  private:
-    /**
-     * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
-     * indicating what the initial user should be.
-     *
-     * During normal circumstances, the emulator will reply right away, passing a response if
-     * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which
-     * user to boot).
-     *
-     * But during development / testing, the behavior can be changed using lshal dump, which must
-     * use the areaId to indicate what should happen next.
-     *
-     * So, the behavior of set(INITIAL_USER_INFO) is:
-     *
-     * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called
-     * by lshal).
-     * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id
-     * and InitialUserInfoResponseAction::DEFAULT
-     * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
-     * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
-     * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can
-     * test this error scenario)
-     * - if it's 3, then don't send a property change (so Android can emulate a timeout)
-     *
-     */
-    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetInitialUserInfoResponse(
-            const VehiclePropValue& value);
-
-    /**
-     * Used to emulate SWITCH_USER - see onSetInitialUserInfoResponse() for usage.
-     */
-    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetSwitchUserResponse(
-            const VehiclePropValue& value);
-
-    /**
-     * Used to emulate CREATE_USER - see onSetInitialUserInfoResponse() for usage.
-     */
-    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetCreateUserResponse(
-            const VehiclePropValue& value);
-
-    /**
-     * Used to emulate set USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
-     * usage.
-     */
-    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetUserIdentificationAssociation(
-            const VehiclePropValue& value);
-
-    /**
-     * Used to emulate get USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
-     * usage.
-     */
-    android::base::Result<std::unique_ptr<VehiclePropValue>> onGetUserIdentificationAssociation(
-            const VehiclePropValue& value);
-
-    /**
-     * Creates a default USER_IDENTIFICATION_ASSOCIATION when it was not set by lshal.
-     */
-    android::base::Result<std::unique_ptr<VehiclePropValue>> defaultUserIdentificationAssociation(
-            const VehiclePropValue& request);
-
-    android::base::Result<std::unique_ptr<VehiclePropValue>> sendUserHalResponse(
-            std::unique_ptr<VehiclePropValue> response, int32_t requestId);
-
-    std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
-    std::unique_ptr<VehiclePropValue> mSwitchUserResponseFromCmd;
-    std::unique_ptr<VehiclePropValue> mCreateUserResponseFromCmd;
-    std::unique_ptr<VehiclePropValue> mSetUserIdentificationAssociationResponseFromCmd;
-};
-
-}  // namespace impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
deleted file mode 100644
index eae58d0..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "automotive.vehicle@2.0-connector"
-
-#include <fstream>
-
-#include <android-base/logging.h>
-#include <utils/SystemClock.h>
-
-#include "EmulatedVehicleConnector.h"
-#include "JsonFakeValueGenerator.h"
-#include "LinearFakeValueGenerator.h"
-#include "Obd2SensorStore.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-EmulatedUserHal* EmulatedVehicleConnector::getEmulatedUserHal() {
-    return &mEmulatedUserHal;
-}
-
-void EmulatedVehicleConnector::triggerSendAllValues() {
-    sendAllValuesToClient();
-}
-
-StatusCode EmulatedVehicleConnector::onSetProperty(const VehiclePropValue& value,
-                                                   bool updateStatus) {
-    if (mEmulatedUserHal.isSupported(value.prop)) {
-        LOG(INFO) << "onSetProperty(): property " << value.prop << " will be handled by UserHal";
-
-        const auto& ret = mEmulatedUserHal.onSetProperty(value);
-        if (!ret.ok()) {
-            LOG(ERROR) << "onSetProperty(): HAL returned error: " << ret.error().message();
-            return StatusCode(ret.error().code());
-        }
-        auto updatedValue = ret.value().get();
-        if (updatedValue != nullptr) {
-            LOG(INFO) << "onSetProperty(): updating property returned by HAL: "
-                      << toString(*updatedValue);
-            onPropertyValueFromCar(*updatedValue, updateStatus);
-        }
-        return StatusCode::OK;
-    }
-    return this->VehicleHalServer::onSetProperty(value, updateStatus);
-}
-
-bool EmulatedVehicleConnector::onDump(const hidl_handle& handle,
-                                      const hidl_vec<hidl_string>& options) {
-    int fd = handle->data[0];
-
-    if (options.size() > 0) {
-        if (options[0] == "--help") {
-            dprintf(fd, "Emulator-specific usage:\n");
-            mEmulatedUserHal.showDumpHelp(fd);
-            dprintf(fd, "\n");
-            // Include caller's help options
-            return true;
-        } else if (options[0] == kUserHalDumpOption) {
-            mEmulatedUserHal.dump(fd, "");
-            return false;
-
-        } else {
-            // Let caller handle the options...
-            return true;
-        }
-    }
-
-    dprintf(fd, "Emulator-specific state:\n");
-    mEmulatedUserHal.dump(fd, "  ");
-    dprintf(fd, "\n");
-
-    return true;
-}
-
-}  // namespace impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
deleted file mode 100644
index 31ac7d8..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
-
-#include <vhal_v2_0/VehicleConnector.h>
-
-#include "EmulatedUserHal.h"
-#include "VehicleHalClient.h"
-#include "VehicleHalServer.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-class EmulatedVehicleConnector : public IPassThroughConnector<VehicleHalClient, VehicleHalServer> {
-  public:
-    EmulatedVehicleConnector() = default;
-
-    EmulatedUserHal* getEmulatedUserHal();
-
-    // Methods from VehicleHalServer
-    void triggerSendAllValues() override;
-
-    StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
-
-    bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-
-  private:
-    EmulatedUserHal mEmulatedUserHal;
-};
-
-}  // namespace impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
deleted file mode 100644
index e8b79dc..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ /dev/null
@@ -1,532 +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.
- */
-#define LOG_TAG "DefaultVehicleHal_v2_0"
-
-#include <android-base/chrono_utils.h>
-#include <android-base/macros.h>
-#include <android-base/properties.h>
-#include <android/log.h>
-#include <dirent.h>
-#include <sys/system_properties.h>
-#include <utils/SystemClock.h>
-#include <fstream>
-#include <regex>
-
-#include "EmulatedVehicleHal.h"
-#include "JsonFakeValueGenerator.h"
-#include "LinearFakeValueGenerator.h"
-#include "Obd2SensorStore.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-static constexpr std::chrono::nanoseconds kHeartBeatIntervalNs = 3s;
-
-static std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(size_t numVendorIntegerSensors,
-                                                             size_t numVendorFloatSensors) {
-    std::unique_ptr<Obd2SensorStore> sensorStore(
-        new Obd2SensorStore(numVendorIntegerSensors, numVendorFloatSensors));
-
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_SYSTEM_STATUS,
-                                  toInt(Obd2FuelSystemStatus::CLOSED_LOOP));
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
-                                  toInt(Obd2IgnitionMonitorKind::SPARK));
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
-                                  Obd2CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
-                                      Obd2CommonIgnitionMonitors::MISFIRE_AVAILABLE |
-                                      Obd2SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
-                                      Obd2SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
-                                  toInt(Obd2SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
-    sensorStore->setIntegerSensor(
-        DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
-    sensorStore->setIntegerSensor(
-        DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
-    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_TYPE,
-                                  toInt(Obd2FuelType::GASOLINE));
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ENGINE_RPM, 1250.);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::VEHICLE_SPEED, 40.);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::TIMING_ADVANCE, 2.5);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::THROTTLE_POSITION, 19.75);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE,
-                                -0.373);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1,
-                                190.);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
-    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
-
-    return sensorStore;
-}
-
-EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client,
-                                       EmulatedUserHal* emulatedUserHal)
-    : mPropStore(propStore),
-      mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
-      mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this,
-                                std::placeholders::_1)),
-      mVehicleClient(client),
-      mEmulatedUserHal(emulatedUserHal) {
-    initStaticConfig();
-    mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue,
-                                                            this, std::placeholders::_1,
-                                                            std::placeholders::_2));
-
-    mInitVhalValueOverride =
-            android::base::GetBoolProperty("persist.vendor.vhal_init_value_override", false);
-    if (mInitVhalValueOverride) {
-        getAllPropertiesOverride();
-    }
-}
-
-void EmulatedVehicleHal::getAllPropertiesOverride() {
-    if (auto dir = opendir("/vendor/etc/vhaloverride/")) {
-        std::regex reg_json(".*[.]json", std::regex::icase);
-        while (auto f = readdir(dir)) {
-            if (!regex_match(f->d_name, reg_json)) {
-                continue;
-            }
-            std::string file = "/vendor/etc/vhaloverride/" + std::string(f->d_name);
-            JsonFakeValueGenerator tmpGenerator(file);
-
-            std::vector<VehiclePropValue> propvalues = tmpGenerator.getAllEvents();
-            mVehiclePropertiesOverride.insert(std::end(mVehiclePropertiesOverride),
-                                              std::begin(propvalues), std::end(propvalues));
-        }
-        closedir(dir);
-    }
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
-        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
-    auto propId = requestedPropValue.prop;
-    ALOGV("get(%d)", propId);
-
-    auto& pool = *getValuePool();
-    VehiclePropValuePtr v = nullptr;
-
-    switch (propId) {
-        case OBD2_FREEZE_FRAME:
-            v = pool.obtainComplex();
-            *outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
-            break;
-        case OBD2_FREEZE_FRAME_INFO:
-            v = pool.obtainComplex();
-            *outStatus = fillObd2DtcInfo(v.get());
-            break;
-        default:
-            if (mEmulatedUserHal != nullptr && mEmulatedUserHal->isSupported(propId)) {
-                ALOGI("get(): getting value for prop %d from User HAL", propId);
-                const auto& ret = mEmulatedUserHal->onGetProperty(requestedPropValue);
-                if (!ret.ok()) {
-                    ALOGE("get(): User HAL returned error: %s", ret.error().message().c_str());
-                    *outStatus = StatusCode(ret.error().code());
-                } else {
-                    auto value = ret.value().get();
-                    if (value != nullptr) {
-                        ALOGI("get(): User HAL returned value: %s", toString(*value).c_str());
-                        v = getValuePool()->obtain(*value);
-                        *outStatus = StatusCode::OK;
-                    } else {
-                        ALOGE("get(): User HAL returned null value");
-                        *outStatus = StatusCode::INTERNAL_ERROR;
-                    }
-                }
-                break;
-            }
-
-            auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
-            if (internalPropValue != nullptr) {
-                v = getValuePool()->obtain(*internalPropValue);
-            }
-
-            if (!v) {
-                *outStatus = StatusCode::INVALID_ARG;
-            } else if (v->status == VehiclePropertyStatus::AVAILABLE) {
-                *outStatus = StatusCode::OK;
-            } else {
-                *outStatus = StatusCode::TRY_AGAIN;
-            }
-            break;
-    }
-    if (v.get()) {
-        v->timestamp = elapsedRealtimeNano();
-    }
-    return v;
-}
-
-bool EmulatedVehicleHal::dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
-    return mVehicleClient->dump(fd, options);
-}
-
-StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
-    constexpr bool updateStatus = false;
-
-    if (propValue.prop == kGenerateFakeDataControllingProperty) {
-        // Send the generator controlling request to the server.
-        // 'updateStatus' flag is only for the value sent by setProperty (propValue in this case)
-        // instead of the generated values triggered by it. 'propValue' works as a control signal
-        // here, since we never send the control signal back, the value of 'updateStatus' flag
-        // does not matter here.
-        auto status = mVehicleClient->setProperty(propValue, updateStatus);
-        return status;
-    } else if (mHvacPowerProps.count(propValue.prop)) {
-        auto hvacPowerOn = mPropStore->readValueOrNull(
-            toInt(VehicleProperty::HVAC_POWER_ON),
-            (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT |
-             VehicleAreaSeat::ROW_2_LEFT | VehicleAreaSeat::ROW_2_CENTER |
-             VehicleAreaSeat::ROW_2_RIGHT));
-
-        if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
-                && hvacPowerOn->value.int32Values[0] == 0) {
-            return StatusCode::NOT_AVAILABLE;
-        }
-    } else {
-        // Handle property specific code
-        switch (propValue.prop) {
-            case OBD2_FREEZE_FRAME_CLEAR:
-                return clearObd2FreezeFrames(propValue);
-            case VEHICLE_MAP_SERVICE:
-                // Placeholder for future implementation of VMS property in the default hal. For
-                // now, just returns OK; otherwise, hal clients crash with property not supported.
-                return StatusCode::OK;
-        }
-    }
-
-    if (propValue.status != VehiclePropertyStatus::AVAILABLE) {
-        // Android side cannot set property status - this value is the
-        // purview of the HAL implementation to reflect the state of
-        // its underlying hardware
-        return StatusCode::INVALID_ARG;
-    }
-    auto currentPropValue = mPropStore->readValueOrNull(propValue);
-
-    if (currentPropValue == nullptr) {
-        return StatusCode::INVALID_ARG;
-    }
-    if (currentPropValue->status != VehiclePropertyStatus::AVAILABLE) {
-        // do not allow Android side to set() a disabled/error property
-        return StatusCode::NOT_AVAILABLE;
-    }
-
-    if (mInEmulator && propValue.prop == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) {
-        // Emulator does not support remote brightness control, b/139959479
-        // do not send it down so that it does not bring unnecessary property change event
-        // return other error code, such NOT_AVAILABLE, causes Emulator to be freezing
-        // TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixed
-        return StatusCode::OK;
-    }
-
-    /**
-     * After checking all conditions, such as the property is available, a real vhal will
-     * sent the events to Car ECU to take actions.
-     */
-
-    // Send the value to the vehicle server, the server will talk to the (real or emulated) car
-    auto setValueStatus = mVehicleClient->setProperty(propValue, updateStatus);
-    if (setValueStatus != StatusCode::OK) {
-        return setValueStatus;
-    }
-
-    return StatusCode::OK;
-}
-
-static bool isDiagnosticProperty(VehiclePropConfig propConfig) {
-    switch (propConfig.prop) {
-        case OBD2_LIVE_FRAME:
-        case OBD2_FREEZE_FRAME:
-        case OBD2_FREEZE_FRAME_CLEAR:
-        case OBD2_FREEZE_FRAME_INFO:
-            return true;
-    }
-    return false;
-}
-
-// Parse supported properties list and generate vector of property values to hold current values.
-void EmulatedVehicleHal::onCreate() {
-    static constexpr bool shouldUpdateStatus = true;
-
-    auto configs = mVehicleClient->getAllPropertyConfig();
-
-    for (const auto& cfg : configs) {
-        if (isDiagnosticProperty(cfg)) {
-            // do not write an initial empty value for the diagnostic properties
-            // as we will initialize those separately.
-            continue;
-        }
-
-        int32_t numAreas = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs.size();
-
-        for (int i = 0; i < numAreas; i++) {
-            int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId;
-
-            // Create a separate instance for each individual zone
-            VehiclePropValue prop = {
-                    .areaId = curArea,
-                    .prop = cfg.prop,
-                    .status = VehiclePropertyStatus::UNAVAILABLE,
-            };
-
-            if (mInitVhalValueOverride) {
-                for (auto& itOverride : mVehiclePropertiesOverride) {
-                    if (itOverride.prop == cfg.prop) {
-                        prop.status = VehiclePropertyStatus::AVAILABLE;
-                        prop.value = itOverride.value;
-                    }
-                }
-            }
-            mPropStore->writeValue(prop, shouldUpdateStatus);
-        }
-    }
-
-    mVehicleClient->triggerSendAllValues();
-
-    initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
-    initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
-    mInEmulator = isInEmulator();
-    ALOGD("mInEmulator=%s", mInEmulator ? "true" : "false");
-    mRecurrentTimer.registerRecurrentEvent(kHeartBeatIntervalNs,
-                                           static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT));
-}
-
-std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties()  {
-    return mPropStore->getAllConfigs();
-}
-
-void EmulatedVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
-    VehiclePropValuePtr v;
-
-    auto& pool = *getValuePool();
-
-    for (int32_t property : properties) {
-        if (isContinuousProperty(property)) {
-            auto internalPropValue = mPropStore->readValueOrNull(property);
-            if (internalPropValue != nullptr) {
-                v = pool.obtain(*internalPropValue);
-            }
-        } else if (property == static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT)) {
-            // VHAL_HEARTBEAT is not a continuous value, but it needs to be updated periodically.
-            // So, the update is done through onContinuousPropertyTimer.
-            v = doInternalHealthCheck();
-        } else {
-            ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
-        }
-
-        if (v.get()) {
-            v->timestamp = elapsedRealtimeNano();
-            doHalEvent(std::move(v));
-        }
-    }
-}
-
-StatusCode EmulatedVehicleHal::subscribe(int32_t property, float sampleRate) {
-    ALOGI("%s propId: 0x%x, sampleRate: %f", __func__, property, sampleRate);
-
-    if (isContinuousProperty(property)) {
-        mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);
-    }
-    return StatusCode::OK;
-}
-
-StatusCode EmulatedVehicleHal::unsubscribe(int32_t property) {
-    ALOGI("%s propId: 0x%x", __func__, property);
-    if (isContinuousProperty(property)) {
-        mRecurrentTimer.unregisterRecurrentEvent(property);
-    }
-    return StatusCode::OK;
-}
-
-bool EmulatedVehicleHal::isContinuousProperty(int32_t propId) const {
-    const VehiclePropConfig* config = mPropStore->getConfigOrNull(propId);
-    if (config == nullptr) {
-        ALOGW("Config not found for property: 0x%x", propId);
-        return false;
-    }
-    return config->changeMode == VehiclePropertyChangeMode::CONTINUOUS;
-}
-
-bool EmulatedVehicleHal::setPropertyFromVehicle(const VehiclePropValue& propValue) {
-    constexpr bool updateStatus = true;
-    return mVehicleClient->setProperty(propValue, updateStatus) == StatusCode::OK;
-}
-
-std::vector<VehiclePropValue> EmulatedVehicleHal::getAllProperties() const  {
-    return mPropStore->readAllValues();
-}
-
-void EmulatedVehicleHal::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
-    VehiclePropValuePtr updatedPropValue = getValuePool()->obtain(value);
-
-    if (mPropStore->writeValue(*updatedPropValue, updateStatus)) {
-        getEmulatorOrDie()->doSetValueFromClient(*updatedPropValue);
-        doHalEvent(std::move(updatedPropValue));
-    }
-}
-
-void EmulatedVehicleHal::initStaticConfig() {
-    auto configs = mVehicleClient->getAllPropertyConfig();
-    for (auto&& cfg : configs) {
-        VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
-
-        switch (cfg.prop) {
-            case OBD2_FREEZE_FRAME: {
-                tokenFunction = [](const VehiclePropValue& propValue) {
-                    return propValue.timestamp;
-                };
-                break;
-            }
-            default:
-                break;
-        }
-
-        mPropStore->registerProperty(cfg, tokenFunction);
-    }
-}
-
-void EmulatedVehicleHal::initObd2LiveFrame(const VehiclePropConfig& propConfig) {
-    static constexpr bool shouldUpdateStatus = true;
-
-    auto liveObd2Frame = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
-    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
-                                            static_cast<size_t>(propConfig.configArray[1]));
-    sensorStore->fillPropValue("", liveObd2Frame.get());
-    liveObd2Frame->prop = OBD2_LIVE_FRAME;
-
-    mPropStore->writeValue(*liveObd2Frame, shouldUpdateStatus);
-}
-
-void EmulatedVehicleHal::initObd2FreezeFrame(const VehiclePropConfig& propConfig) {
-    static constexpr bool shouldUpdateStatus = true;
-
-    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
-                                            static_cast<size_t>(propConfig.configArray[1]));
-
-    static std::vector<std::string> sampleDtcs = {"P0070",
-                                                  "P0102"
-                                                  "P0123"};
-    for (auto&& dtc : sampleDtcs) {
-        auto freezeFrame = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
-        sensorStore->fillPropValue(dtc, freezeFrame.get());
-        freezeFrame->prop = OBD2_FREEZE_FRAME;
-
-        mPropStore->writeValue(*freezeFrame, shouldUpdateStatus);
-    }
-}
-
-StatusCode EmulatedVehicleHal::fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
-                                                   VehiclePropValue* outValue) {
-    if (requestedPropValue.value.int64Values.size() != 1) {
-        ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
-        return StatusCode::INVALID_ARG;
-    }
-    auto timestamp = requestedPropValue.value.int64Values[0];
-    auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
-    if (freezeFrame == nullptr) {
-        ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
-        return StatusCode::INVALID_ARG;
-    }
-    outValue->prop = OBD2_FREEZE_FRAME;
-    outValue->value.int32Values = freezeFrame->value.int32Values;
-    outValue->value.floatValues = freezeFrame->value.floatValues;
-    outValue->value.bytes = freezeFrame->value.bytes;
-    outValue->value.stringValue = freezeFrame->value.stringValue;
-    outValue->timestamp = freezeFrame->timestamp;
-    return StatusCode::OK;
-}
-
-StatusCode EmulatedVehicleHal::clearObd2FreezeFrames(const VehiclePropValue& propValue) {
-    if (propValue.value.int64Values.size() == 0) {
-        mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
-        return StatusCode::OK;
-    } else {
-        for (int64_t timestamp : propValue.value.int64Values) {
-            auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
-            if (freezeFrame == nullptr) {
-                ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
-                return StatusCode::INVALID_ARG;
-            }
-            mPropStore->removeValue(*freezeFrame);
-        }
-    }
-    return StatusCode::OK;
-}
-
-StatusCode EmulatedVehicleHal::fillObd2DtcInfo(VehiclePropValue* outValue) {
-    std::vector<int64_t> timestamps;
-    for (const auto& freezeFrame : mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME)) {
-        timestamps.push_back(freezeFrame.timestamp);
-    }
-    outValue->value.int64Values = timestamps;
-    outValue->prop = OBD2_FREEZE_FRAME_INFO;
-    return StatusCode::OK;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::doInternalHealthCheck() {
-    VehicleHal::VehiclePropValuePtr v = nullptr;
-
-    // This is an example of very simpe health checking. VHAL is considered healthy if we can read
-    // PERF_VEHICLE_SPEED. The more comprehensive health checking is required.
-    VehiclePropValue propValue = {
-            .prop = static_cast<int32_t>(VehicleProperty::PERF_VEHICLE_SPEED),
-    };
-    auto internalPropValue = mPropStore->readValueOrNull(propValue);
-    if (internalPropValue != nullptr) {
-        v = createVhalHeartBeatProp();
-    } else {
-        ALOGW("VHAL health check failed");
-    }
-    return v;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::createVhalHeartBeatProp() {
-    VehicleHal::VehiclePropValuePtr v = getValuePool()->obtainInt64(uptimeMillis());
-    v->prop = static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT);
-    v->areaId = 0;
-    v->status = VehiclePropertyStatus::AVAILABLE;
-    return v;
-}
-
-}  // impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index 7871c7b..1387f85 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,26 +14,14 @@
  * limitations under the License.
  */
 
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
+// This file is just used for soft migration from EmulatedVehicleHal to DefaultVehicleHal.
+// The virtualized VHAL that uses EmulatedVehicleHal is at a different repo and cannot be updated
+// together with this repo, so we need a soft migration. Once the rename is finished at the
+// virtualized VHAL side, this file would be removed.
 
-#include <map>
-#include <memory>
-#include <sys/socket.h>
-#include <thread>
-#include <unordered_set>
+#pragma once
 
-#include <utils/SystemClock.h>
-
-#include <vhal_v2_0/RecurrentTimer.h>
-#include <vhal_v2_0/VehicleHal.h>
-#include "vhal_v2_0/VehiclePropertyStore.h"
-
-#include "EmulatedUserHal.h"
-#include "EmulatedVehicleConnector.h"
-#include "GeneratorHub.h"
-#include "PropertyUtils.h"
-#include "VehicleEmulator.h"
+#include "DefaultVehicleHal.h"
 
 namespace android {
 namespace hardware {
@@ -43,66 +31,16 @@
 
 namespace impl {
 
-/** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */
-class EmulatedVehicleHal : public EmulatedVehicleHalIface {
-public:
-    EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client,
-                       EmulatedUserHal* emulatedUserHal = nullptr);
-    ~EmulatedVehicleHal() = default;
-
-    //  Methods from VehicleHal
-    void onCreate() override;
-    std::vector<VehiclePropConfig> listProperties() override;
-    VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
-                            StatusCode* outStatus) override;
-    StatusCode set(const VehiclePropValue& propValue) override;
-    StatusCode subscribe(int32_t property, float sampleRate) override;
-    StatusCode unsubscribe(int32_t property) override;
-    bool dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-
-    //  Methods from EmulatedVehicleHalIface
-    bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
-    std::vector<VehiclePropValue> getAllProperties() const override;
-    void getAllPropertiesOverride();
-
-private:
-    constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
-        return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
-    }
-
-    StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
-    void onPropertyValue(const VehiclePropValue& value, bool updateStatus);
-
-    void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
-    bool isContinuousProperty(int32_t propId) const;
-    void initStaticConfig();
-    void initObd2LiveFrame(const VehiclePropConfig& propConfig);
-    void initObd2FreezeFrame(const VehiclePropConfig& propConfig);
-    StatusCode fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
-                                   VehiclePropValue* outValue);
-    StatusCode fillObd2DtcInfo(VehiclePropValue* outValue);
-    StatusCode clearObd2FreezeFrames(const VehiclePropValue& propValue);
-    VehicleHal::VehiclePropValuePtr doInternalHealthCheck();
-    VehicleHal::VehiclePropValuePtr createVhalHeartBeatProp();
-
-    /* Private members */
-    VehiclePropertyStore* mPropStore;
-    std::unordered_set<int32_t> mHvacPowerProps;
-    RecurrentTimer mRecurrentTimer;
-    VehicleHalClient* mVehicleClient;
-    bool mInEmulator;
-    bool mInitVhalValueOverride;
-    std::vector<VehiclePropValue> mVehiclePropertiesOverride;
-    EmulatedUserHal* mEmulatedUserHal;
+class EmulatedVehicleHal : public DefaultVehicleHal {
+  public:
+    EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
+        : DefaultVehicleHal(propStore, client){};
 };
 
-}  // impl
+}  // namespace impl
 
 }  // namespace V2_0
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
 }  // namespace android
-
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeObd2Frame.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeObd2Frame.cpp
new file mode 100644
index 0000000..d95584d
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeObd2Frame.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include <utils/Log.h>
+#include <vhal_v2_0/Obd2SensorStore.h>
+#include <vhal_v2_0/PropertyUtils.h>
+#include <vhal_v2_0/VehiclePropertyStore.h>
+#include <vhal_v2_0/VehicleUtils.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+namespace {
+
+std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(size_t numVendorIntegerSensors,
+                                                      size_t numVendorFloatSensors) {
+    std::unique_ptr<Obd2SensorStore> sensorStore(
+            new Obd2SensorStore(numVendorIntegerSensors, numVendorFloatSensors));
+
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_SYSTEM_STATUS,
+                                  toInt(Obd2FuelSystemStatus::CLOSED_LOOP));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
+                                  toInt(Obd2IgnitionMonitorKind::SPARK));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
+                                  Obd2CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
+                                          Obd2CommonIgnitionMonitors::MISFIRE_AVAILABLE |
+                                          Obd2SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
+                                          Obd2SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
+                                  toInt(Obd2SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
+    sensorStore->setIntegerSensor(
+            DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
+    sensorStore->setIntegerSensor(
+            DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_TYPE,
+                                  toInt(Obd2FuelType::GASOLINE));
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ENGINE_RPM, 1250.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::VEHICLE_SPEED, 40.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::TIMING_ADVANCE, 2.5);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::THROTTLE_POSITION, 19.75);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE,
+                                -0.373);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1,
+                                190.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
+
+    return sensorStore;
+}
+
+}  // namespace
+
+void initObd2LiveFrame(VehiclePropertyStore* propStore, const VehiclePropConfig& propConfig) {
+    auto liveObd2Frame = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
+    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+                                            static_cast<size_t>(propConfig.configArray[1]));
+    sensorStore->fillPropValue("", liveObd2Frame.get());
+    liveObd2Frame->prop = OBD2_LIVE_FRAME;
+
+    propStore->writeValue(*liveObd2Frame, true);
+}
+
+void initObd2FreezeFrame(VehiclePropertyStore* propStore, const VehiclePropConfig& propConfig) {
+    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+                                            static_cast<size_t>(propConfig.configArray[1]));
+
+    static std::vector<std::string> sampleDtcs = {"P0070", "P0102", "P0123"};
+    for (auto&& dtc : sampleDtcs) {
+        auto freezeFrame = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
+        sensorStore->fillPropValue(dtc, freezeFrame.get());
+        freezeFrame->prop = OBD2_FREEZE_FRAME;
+        ALOGE("freeze frame: %lld", (long long)freezeFrame->timestamp);
+
+        propStore->writeValue(*freezeFrame, true);
+    }
+}
+
+StatusCode fillObd2FreezeFrame(VehiclePropertyStore* propStore,
+                               const VehiclePropValue& requestedPropValue,
+                               VehiclePropValue* outValue) {
+    if (requestedPropValue.value.int64Values.size() != 1) {
+        ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
+        return StatusCode::INVALID_ARG;
+    }
+    if (propStore->readValuesForProperty(OBD2_FREEZE_FRAME).size() == 0) {
+        // Should no freeze frame be available at the given timestamp, a response of NOT_AVAILABLE
+        // must be returned by the implementation
+        return StatusCode::NOT_AVAILABLE;
+    }
+    auto timestamp = requestedPropValue.value.int64Values[0];
+    auto freezeFrame = propStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
+    if (freezeFrame == nullptr) {
+        ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
+        return StatusCode::INVALID_ARG;
+    }
+    outValue->prop = OBD2_FREEZE_FRAME;
+    outValue->value.int32Values = freezeFrame->value.int32Values;
+    outValue->value.floatValues = freezeFrame->value.floatValues;
+    outValue->value.bytes = freezeFrame->value.bytes;
+    outValue->value.stringValue = freezeFrame->value.stringValue;
+    outValue->timestamp = freezeFrame->timestamp;
+    return StatusCode::OK;
+}
+
+StatusCode fillObd2DtcInfo(VehiclePropertyStore* propStore, VehiclePropValue* outValue) {
+    std::vector<int64_t> timestamps;
+    for (const auto& freezeFrame : propStore->readValuesForProperty(OBD2_FREEZE_FRAME)) {
+        timestamps.push_back(freezeFrame.timestamp);
+    }
+    outValue->value.int64Values = timestamps;
+    outValue->prop = OBD2_FREEZE_FRAME_INFO;
+    return StatusCode::OK;
+}
+
+StatusCode clearObd2FreezeFrames(VehiclePropertyStore* propStore,
+                                 const VehiclePropValue& propValue) {
+    if (propValue.value.int64Values.size() == 0) {
+        propStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
+        return StatusCode::OK;
+    } else {
+        for (int64_t timestamp : propValue.value.int64Values) {
+            auto freezeFrame = propStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
+            if (freezeFrame == nullptr) {
+                ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
+                return StatusCode::INVALID_ARG;
+            }
+            propStore->removeValue(*freezeFrame);
+        }
+    }
+    return StatusCode::OK;
+}
+
+bool isDiagnosticProperty(const VehiclePropConfig& propConfig) {
+    return (propConfig.prop == OBD2_LIVE_FRAME || propConfig.prop == OBD2_FREEZE_FRAME ||
+            propConfig.prop == OBD2_FREEZE_FRAME_CLEAR ||
+            propConfig.prop == OBD2_FREEZE_FRAME_INFO);
+}
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeObd2Frame.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeObd2Frame.h
new file mode 100644
index 0000000..704964c
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeObd2Frame.h
@@ -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.
+ */
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_FakeObd2Frame_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_FakeObd2Frame_H_
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include <vhal_v2_0/VehiclePropertyStore.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+void initObd2LiveFrame(VehiclePropertyStore* propStore, const VehiclePropConfig& propConfig);
+void initObd2FreezeFrame(VehiclePropertyStore* propStore, const VehiclePropConfig& propConfig);
+StatusCode fillObd2FreezeFrame(VehiclePropertyStore* propStore,
+                               const VehiclePropValue& requestedPropValue,
+                               VehiclePropValue* outValue);
+StatusCode fillObd2DtcInfo(VehiclePropertyStore* propStore, VehiclePropValue* outValue);
+StatusCode clearObd2FreezeFrames(VehiclePropertyStore* propStore,
+                                 const VehiclePropValue& propValue);
+bool isDiagnosticProperty(const VehiclePropConfig& propConfig);
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_FakeObd2Frame_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
index b62918f..b728d62 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
@@ -33,12 +33,37 @@
 
 namespace impl {
 
+JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path, int32_t repetition) {
+    const char* file = path.c_str();
+    std::ifstream ifs(file);
+    if (!ifs) {
+        ALOGE("%s: couldn't open %s for parsing.", __func__, file);
+        mGenCfg = {
+                .index = 0,
+                .events = {},
+        };
+        mNumOfIterations = 0;
+        return;
+    }
+    mGenCfg = {
+            .index = 0,
+            .events = parseFakeValueJson(ifs),
+    };
+    mNumOfIterations = repetition;
+}
+
 JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) {
     const auto& v = request.value;
     const char* file = v.stringValue.c_str();
     std::ifstream ifs(file);
     if (!ifs) {
         ALOGE("%s: couldn't open %s for parsing.", __func__, file);
+        mGenCfg = {
+                .index = 0,
+                .events = {},
+        };
+        mNumOfIterations = 0;
+        return;
     }
     mGenCfg = {
         .index = 0,
@@ -48,10 +73,16 @@
     mNumOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
 }
 
-JsonFakeValueGenerator::JsonFakeValueGenerator(std::string path) {
+JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path) {
     std::ifstream ifs(path);
     if (!ifs) {
         ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str());
+        mGenCfg = {
+                .index = 0,
+                .events = {},
+        };
+        mNumOfIterations = 0;
+        return;
     }
     mGenCfg = {
         .index = 0,
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
index dc8ff66..caa3417 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
@@ -41,7 +41,8 @@
 
 public:
     JsonFakeValueGenerator(const VehiclePropValue& request);
-    JsonFakeValueGenerator(std::string path);
+    JsonFakeValueGenerator(const std::string& path, int32_t repetition);
+    JsonFakeValueGenerator(const std::string& path);
 
     ~JsonFakeValueGenerator() = default;
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
index 96aaafe..a2278bd 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
@@ -29,23 +29,36 @@
 
 namespace impl {
 
+LinearFakeValueGenerator::LinearFakeValueGenerator(int32_t propId, float middleValue,
+                                                   float currentValue, float dispersion,
+                                                   float increment, int64_t interval) {
+    initGenCfg(propId, middleValue, currentValue, dispersion, increment, interval);
+}
+
 LinearFakeValueGenerator::LinearFakeValueGenerator(const VehiclePropValue& request) {
     const auto& v = request.value;
+    initGenCfg(v.int32Values[1], v.floatValues[0], v.floatValues[0], v.floatValues[1],
+               v.floatValues[2], v.int64Values[0]);
+}
+
+void LinearFakeValueGenerator::initGenCfg(int32_t propId, float middleValue, float currentValue,
+                                          float dispersion, float increment, int64_t interval) {
+    if (currentValue < middleValue - dispersion || currentValue >= middleValue + dispersion) {
+        ALOGW("%s: invalid initValue: %f, out of range, default to %f", __func__, currentValue,
+              middleValue);
+        currentValue = middleValue;
+    }
     mGenCfg = GeneratorCfg{
-        .propId = v.int32Values[1],
-        .initialValue = v.floatValues[0],
-        .currentValue = v.floatValues[0],
-        .dispersion = v.floatValues[1],
-        .increment = v.floatValues[2],
-        .interval = Nanos(v.int64Values[0]),
+            .propId = propId,
+            .middleValue = middleValue,
+            .currentValue = currentValue,
+            .dispersion = dispersion,
+            .increment = increment,
+            .interval = Nanos(interval),
     };
 }
 
 VehiclePropValue LinearFakeValueGenerator::nextEvent() {
-    mGenCfg.currentValue += mGenCfg.increment;
-    if (mGenCfg.currentValue > mGenCfg.initialValue + mGenCfg.dispersion) {
-        mGenCfg.currentValue = mGenCfg.initialValue - mGenCfg.dispersion;
-    }
     // TODO: (chenhaosjtuacm) remove "{}" if AGL compiler updated
     VehiclePropValue event = {.timestamp = {}, .areaId = {}, .prop = mGenCfg.propId};
     auto& value = event.value;
@@ -67,6 +80,12 @@
     }
     TimePoint eventTime = Clock::now() + mGenCfg.interval;
     event.timestamp = eventTime.time_since_epoch().count();
+
+    mGenCfg.currentValue += mGenCfg.increment;
+    if (mGenCfg.currentValue >= mGenCfg.middleValue + mGenCfg.dispersion) {
+        // Wrap around, (i - d) + c - (i + d) = c - 2 * d
+        mGenCfg.currentValue = mGenCfg.currentValue - 2 * mGenCfg.dispersion;
+    }
     return event;
 }
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
index d3b666d..d870209 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
@@ -35,8 +35,8 @@
 
     struct GeneratorCfg {
         int32_t propId;
-        float initialValue;
-        float currentValue;  //  Should be in range (initialValue +/- dispersion).
+        float middleValue;
+        float currentValue;  //  Should be in range (middleValue +/- dispersion).
         float dispersion;    //  Defines minimum and maximum value based on initial value.
         float increment;     //  Value that we will be added to currentValue with each timer tick.
         Nanos interval;
@@ -44,6 +44,11 @@
 
 public:
     LinearFakeValueGenerator(const VehiclePropValue& request);
+    // A linear value generator in range [middleValue - dispersion, middleValue + dispersion),
+    // starts at 'currentValue' and at each 'interval', increase by 'increment' and loop back if
+    // exceeds middleValue + dispersion.
+    LinearFakeValueGenerator(int32_t propId, float middleValue, float currentValue,
+                             float dispersion, float increment, int64_t interval);
     ~LinearFakeValueGenerator() = default;
 
     VehiclePropValue nextEvent();
@@ -52,6 +57,9 @@
 
 private:
     GeneratorCfg mGenCfg;
+
+    void initGenCfg(int32_t propId, float middleValue, float currentValue, float dispersion,
+                    float increment, int64_t interval);
 };
 
 }  // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
deleted file mode 100644
index 81e7c78..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
+++ /dev/null
@@ -1,105 +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.
- */
-
-#define LOG_TAG "PipeComm"
-
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
-#include <log/log.h>
-
-#include "PipeComm.h"
-#include "qemu_pipe.h"
-
-#define CAR_SERVICE_NAME "pipe:qemud:car"
-
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-PipeComm::PipeComm(MessageProcessor* messageProcessor) : CommConn(messageProcessor), mPipeFd(-1) {}
-
-void PipeComm::start() {
-    int fd = qemu_pipe_open(CAR_SERVICE_NAME);
-
-    if (fd < 0) {
-        ALOGE("%s: Could not open connection to service: %s %d", __FUNCTION__, strerror(errno), fd);
-        return;
-    }
-
-    ALOGI("%s: Starting pipe connection, fd=%d", __FUNCTION__, fd);
-    mPipeFd = fd;
-
-    CommConn::start();
-}
-
-void PipeComm::stop() {
-    if (mPipeFd > 0) {
-        ::close(mPipeFd);
-        mPipeFd = -1;
-    }
-    CommConn::stop();
-}
-
-std::vector<uint8_t> PipeComm::read() {
-    static constexpr int MAX_RX_MSG_SZ = 2048;
-    std::vector<uint8_t> msg = std::vector<uint8_t>(MAX_RX_MSG_SZ);
-    int numBytes;
-
-    numBytes = qemu_pipe_frame_recv(mPipeFd, msg.data(), msg.size());
-
-    if (numBytes == MAX_RX_MSG_SZ) {
-        ALOGE("%s: Received max size = %d", __FUNCTION__, MAX_RX_MSG_SZ);
-    } else if (numBytes > 0) {
-        msg.resize(numBytes);
-        return msg;
-    } else {
-        ALOGD("%s: Connection terminated on pipe %d, numBytes=%d", __FUNCTION__, mPipeFd, numBytes);
-        mPipeFd = -1;
-    }
-
-    return std::vector<uint8_t>();
-}
-
-int PipeComm::write(const std::vector<uint8_t>& data) {
-    int retVal = 0;
-
-    if (mPipeFd != -1) {
-        retVal = qemu_pipe_frame_send(mPipeFd, data.data(), data.size());
-    }
-
-    if (retVal < 0) {
-        retVal = -errno;
-        ALOGE("%s:  send_cmd: (fd=%d): ERROR: %s", __FUNCTION__, mPipeFd, strerror(errno));
-    }
-
-    return retVal;
-}
-
-
-}  // impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-
-
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h
deleted file mode 100644
index c8eabb8..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h
+++ /dev/null
@@ -1,64 +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 android_hardware_automotive_vehicle_V2_0_impl_PipeComm_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_PipeComm_H_
-
-#include <mutex>
-#include <vector>
-#include "CommConn.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-/**
- * PipeComm opens a qemu pipe to connect to the emulator, allowing the emulator UI to access the
- * Vehicle HAL and simulate changing properties.
- *
- * Since the pipe is a client, it directly implements CommConn, and only one PipeComm can be open
- * at a time.
- */
-class PipeComm : public CommConn {
-   public:
-    PipeComm(MessageProcessor* messageProcessor);
-
-    void start() override;
-    void stop() override;
-
-    std::vector<uint8_t> read() override;
-    int write(const std::vector<uint8_t>& data) override;
-
-    inline bool isOpen() override { return mPipeFd > 0; }
-
-   private:
-    int mPipeFd;
-};
-
-}  // impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_PipeComm_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
index 51251a7..f58e09a 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
@@ -37,6 +37,7 @@
 constexpr int WINDOW_ROOF_TOP_1 = (int)VehicleAreaWindow::ROOF_TOP_1;
 constexpr int FAN_DIRECTION_FACE = (int)VehicleHvacFanDirection::FACE;
 constexpr int FAN_DIRECTION_FLOOR = (int)VehicleHvacFanDirection::FLOOR;
+constexpr int FAN_DIRECTION_DEFROST = (int)VehicleHvacFanDirection::DEFROST;
 constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME;
 constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME;
 constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO;
@@ -72,35 +73,6 @@
 constexpr int WHEEL_REAR_RIGHT = (int)VehicleAreaWheel::RIGHT_REAR;
 
 /**
- * This property is used for test purpose to generate fake events. Here is the test package that
- * is referencing this property definition: packages/services/Car/tests/vehiclehal_test
- */
-const int32_t kGenerateFakeDataControllingProperty =
-    0x0666 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
-
-/**
- * This property is used for test purpose to set properties' value from vehicle.
- * For example: Mocking hard button press triggering a HVAC fan speed change.
- * Android set kSetPropertyFromVehicleForTest with an array of integer {HVAC_FAN_SPEED, value of
- * fan speed} and a long value indicates the timestamp of the events .
- * It only works with integer type properties.
- */
-const int32_t kSetIntPropertyFromVehicleForTest =
-        0x1112 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
-/**
- * This property is used for test purpose to set properties' value from vehicle.
- * It only works with float type properties.
- */
-const int32_t kSetFloatPropertyFromVehicleForTest =
-        0x1113 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
-/**
- * This property is used for test purpose to set properties' value from vehicle.
- * It only works with boolean type properties.
- */
-const int32_t kSetBooleanPropertyFromVehicleForTest =
-        0x1114 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
-
-/**
  * This property is used for test purpose. End to end tests use this property to test set and get
  * method for MIXED type properties.
  */
@@ -129,67 +101,6 @@
 #endif  // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
 
 /**
- * FakeDataCommand enum defines the supported command type for kGenerateFakeDataControllingProperty.
- * All those commands can be send independently with each other. And each will override the one sent
- * previously.
- *
- * The controlling property has the following format:
- *
- *     int32Values[0] - command enum defined in FakeDataCommand
- *
- * The format of the arguments is defined for each command type as below:
- */
-enum class FakeDataCommand : int32_t {
-    /**
-     * Starts linear fake data generation. Caller must provide additional data:
-     *     int32Values[1] - vehicle property to which command applies
-     *     int64Values[0] - periodic interval in nanoseconds
-     *     floatValues[0] - initial value
-     *     floatValues[1] - dispersion defines the min/max value relative to initial value, where
-     *                      max = initial_value + dispersion, min = initial_value - dispersion.
-     *                      Dispersion should be non-negative, otherwise the behavior is undefined.
-     *     floatValues[2] - increment, with every timer tick the value will be incremented by this
-     *                      amount. When reaching to max value, the current value will be set to
-     *                      min. It should be non-negative, otherwise the behavior is undefined.
-     */
-    StartLinear = 0,
-
-    /** Stops linear fake data generation that was triggered by StartLinear commands.
-     *     int32Values[1] - vehicle property to which command applies. VHAL will stop the
-     *                      corresponding linear generation for that property.
-     */
-    StopLinear = 1,
-
-    /**
-     * Starts JSON-based fake data generation. It iterates through JSON-encoded VHAL events from a
-     * file and inject them to VHAL. The iteration can be repeated multiple times or infinitely.
-     * Caller must provide additional data:
-     *     int32Values[1] - number of iterations. If it is not provided or -1. The iteration will be
-     *                      repeated infinite times.
-     *     stringValue    - path to the fake values JSON file
-     */
-    StartJson = 2,
-
-    /**
-     * Stops JSON-based fake data generation. As multiple JSON-based generation can happen at the
-     * same time. Caller must provide the path of fake value JSON file to stop the corresponding
-     * generation:
-     *     stringValue    - path to the fake values JSON file
-     */
-    StopJson = 3,
-
-    /**
-     * Injects key press event (HAL incorporates UP/DOWN acction and triggers 2 HAL events for every
-     * key-press). We set the enum with high number to leave space for future start/stop commands.
-     * Caller must provide the following data:
-     *     int32Values[2] - Android key code
-     *     int32Values[3] - target display (0 - for main display, 1 - for instrument cluster, see
-     *                      VehicleDisplay)
-     */
-    KeyPress = 100,
-};
-
-/**
  * These properties are placeholder properties for developers to test new features without
  * implementing a real property.
  */
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
deleted file mode 100644
index 916c320..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
+++ /dev/null
@@ -1,226 +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.
- */
-
-#define LOG_TAG "SocketComm"
-
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
-#include <android/log.h>
-#include <arpa/inet.h>
-#include <log/log.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-#include "SocketComm.h"
-
-// Socket to use when communicating with Host PC
-static constexpr int DEBUG_SOCKET = 33452;
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-SocketComm::SocketComm(MessageProcessor* messageProcessor)
-    : mListenFd(-1), mMessageProcessor(messageProcessor) {}
-
-SocketComm::~SocketComm() {
-}
-
-void SocketComm::start() {
-    if (!listen()) {
-        return;
-    }
-
-    mListenThread = std::make_unique<std::thread>(std::bind(&SocketComm::listenThread, this));
-}
-
-void SocketComm::stop() {
-    if (mListenFd > 0) {
-        ::close(mListenFd);
-        if (mListenThread->joinable()) {
-            mListenThread->join();
-        }
-        mListenFd = -1;
-    }
-}
-
-void SocketComm::sendMessage(vhal_proto::EmulatorMessage const& msg) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    for (std::unique_ptr<SocketConn> const& conn : mOpenConnections) {
-        conn->sendMessage(msg);
-    }
-}
-
-bool SocketComm::listen() {
-    int retVal;
-    struct sockaddr_in servAddr;
-
-    mListenFd = socket(AF_INET, SOCK_STREAM, 0);
-    if (mListenFd < 0) {
-        ALOGE("%s: socket() failed, mSockFd=%d, errno=%d", __FUNCTION__, mListenFd, errno);
-        mListenFd = -1;
-        return false;
-    }
-
-    memset(&servAddr, 0, sizeof(servAddr));
-    servAddr.sin_family = AF_INET;
-    servAddr.sin_addr.s_addr = INADDR_ANY;
-    servAddr.sin_port = htons(DEBUG_SOCKET);
-
-    retVal = bind(mListenFd, reinterpret_cast<struct sockaddr*>(&servAddr), sizeof(servAddr));
-    if(retVal < 0) {
-        ALOGE("%s: Error on binding: retVal=%d, errno=%d", __FUNCTION__, retVal, errno);
-        close(mListenFd);
-        mListenFd = -1;
-        return false;
-    }
-
-    ALOGI("%s: Listening for connections on port %d", __FUNCTION__, DEBUG_SOCKET);
-    if (::listen(mListenFd, 1) == -1) {
-        ALOGE("%s: Error on listening: errno: %d: %s", __FUNCTION__, errno, strerror(errno));
-        return false;
-    }
-    return true;
-}
-
-SocketConn* SocketComm::accept() {
-    sockaddr_in cliAddr;
-    socklen_t cliLen = sizeof(cliAddr);
-    int sfd = ::accept(mListenFd, reinterpret_cast<struct sockaddr*>(&cliAddr), &cliLen);
-
-    if (sfd > 0) {
-        char addr[INET_ADDRSTRLEN];
-        inet_ntop(AF_INET, &cliAddr.sin_addr, addr, INET_ADDRSTRLEN);
-
-        ALOGD("%s: Incoming connection received from %s:%d", __FUNCTION__, addr, cliAddr.sin_port);
-        return new SocketConn(mMessageProcessor, sfd);
-    }
-
-    return nullptr;
-}
-
-void SocketComm::listenThread() {
-    while (true) {
-        SocketConn* conn = accept();
-        if (conn == nullptr) {
-            return;
-        }
-
-        conn->start();
-        {
-            std::lock_guard<std::mutex> lock(mMutex);
-            mOpenConnections.push_back(std::unique_ptr<SocketConn>(conn));
-        }
-    }
-}
-
-/**
- * Called occasionally to clean up connections that have been closed.
- */
-void SocketComm::removeClosedConnections() {
-    std::lock_guard<std::mutex> lock(mMutex);
-    std::remove_if(mOpenConnections.begin(), mOpenConnections.end(),
-                   [](std::unique_ptr<SocketConn> const& c) { return !c->isOpen(); });
-}
-
-SocketConn::SocketConn(MessageProcessor* messageProcessor, int sfd)
-    : CommConn(messageProcessor), mSockFd(sfd) {}
-
-/**
- * Reads, in a loop, exactly numBytes from the given fd. If the connection is closed, returns
- * an empty buffer, otherwise will return exactly the given number of bytes.
- */
-std::vector<uint8_t> readExactly(int fd, int numBytes) {
-    std::vector<uint8_t> buffer(numBytes);
-    int totalRead = 0;
-    int offset = 0;
-    while (totalRead < numBytes) {
-        int numRead = ::read(fd, &buffer.data()[offset], numBytes - offset);
-        if (numRead == 0) {
-            buffer.resize(0);
-            return buffer;
-        }
-
-        totalRead += numRead;
-    }
-    return buffer;
-}
-
-/**
- * Reads an int, guaranteed to be non-zero, from the given fd. If the connection is closed, returns
- * -1.
- */
-int32_t readInt(int fd) {
-    std::vector<uint8_t> buffer = readExactly(fd, sizeof(int32_t));
-    if (buffer.size() == 0) {
-        return -1;
-    }
-
-    int32_t value = *reinterpret_cast<int32_t*>(buffer.data());
-    return ntohl(value);
-}
-
-std::vector<uint8_t> SocketConn::read() {
-    int32_t msgSize = readInt(mSockFd);
-    if (msgSize <= 0) {
-        ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, mSockFd);
-        return std::vector<uint8_t>();
-    }
-
-    return readExactly(mSockFd, msgSize);
-}
-
-void SocketConn::stop() {
-    if (mSockFd > 0) {
-        close(mSockFd);
-        mSockFd = -1;
-    }
-}
-
-int SocketConn::write(const std::vector<uint8_t>& data) {
-    static constexpr int MSG_HEADER_LEN = 4;
-    int retVal = 0;
-    union {
-        uint32_t msgLen;
-        uint8_t msgLenBytes[MSG_HEADER_LEN];
-    };
-
-    // Prepare header for the message
-    msgLen = static_cast<uint32_t>(data.size());
-    msgLen = htonl(msgLen);
-
-    if (mSockFd > 0) {
-        retVal = ::write(mSockFd, msgLenBytes, MSG_HEADER_LEN);
-
-        if (retVal == MSG_HEADER_LEN) {
-            retVal = ::write(mSockFd, data.data(), data.size());
-        }
-    }
-
-    return retVal;
-}
-
-}  // impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h
deleted file mode 100644
index 52326b9..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h
+++ /dev/null
@@ -1,125 +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 android_hardware_automotive_vehicle_V2_0_impl_SocketComm_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_SocketComm_H_
-
-#include <mutex>
-#include <thread>
-#include <vector>
-#include "CommConn.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-class SocketConn;
-
-/**
- * SocketComm opens a socket, and listens for connections from clients. Typically the client will be
- * adb's TCP port-forwarding to enable a host PC to connect to the VehicleHAL.
- */
-class SocketComm {
-   public:
-    SocketComm(MessageProcessor* messageProcessor);
-    virtual ~SocketComm();
-
-    void start();
-    void stop();
-
-    /**
-     * Serialized and send the given message to all connected clients.
-     */
-    void sendMessage(vhal_proto::EmulatorMessage const& msg);
-
-   private:
-    int mListenFd;
-    std::unique_ptr<std::thread> mListenThread;
-    std::vector<std::unique_ptr<SocketConn>> mOpenConnections;
-    MessageProcessor* mMessageProcessor;
-    std::mutex mMutex;
-
-    /**
-     * Opens the socket and begins listening.
-     *
-     * @return bool Returns true on success.
-     */
-    bool listen();
-
-    /**
-     * Blocks and waits for a connection from a client, returns a new SocketConn with the connection
-     * or null, if the connection has been closed.
-     *
-     * @return int Returns fd or socket number if connection is successful.
-     *              Otherwise, returns -1 if no connection is availble.
-     */
-    SocketConn* accept();
-
-    void listenThread();
-
-    void removeClosedConnections();
-};
-
-/**
- * SocketConn represents a single connection to a client.
- */
-class SocketConn : public CommConn {
-   public:
-    SocketConn(MessageProcessor* messageProcessor, int sfd);
-    virtual ~SocketConn() = default;
-
-    /**
-     * Blocking call to read data from the connection.
-     *
-     * @return std::vector<uint8_t> Serialized protobuf data received from emulator.  This will be
-     *              an empty vector if the connection was closed or some other error occurred.
-     */
-    std::vector<uint8_t> read() override;
-
-    /**
-     * Closes a connection if it is open.
-     */
-    void stop() override;
-
-    /**
-     * Transmits a string of data to the emulator.
-     *
-     * @param data Serialized protobuf data to transmit.
-     *
-     * @return int Number of bytes transmitted, or -1 if failed.
-     */
-    int write(const std::vector<uint8_t>& data) override;
-
-    inline bool isOpen() override { return mSockFd > 0; }
-
-   private:
-    int mSockFd;
-};
-
-}  // impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_SocketComm_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
deleted file mode 100644
index f7d0854..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
+++ /dev/null
@@ -1,239 +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.
- */
-#define LOG_TAG "VehicleEmulator_v2_0"
-#include <android/log.h>
-
-#include <android-base/properties.h>
-#include <log/log.h>
-#include <utils/SystemClock.h>
-#include <algorithm>
-
-#include <vhal_v2_0/VehicleUtils.h>
-
-#include "PipeComm.h"
-#include "ProtoMessageConverter.h"
-#include "SocketComm.h"
-
-#include "VehicleEmulator.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-VehicleEmulator::VehicleEmulator(EmulatedVehicleHalIface* hal) : mHal{hal} {
-    mHal->registerEmulator(this);
-
-    ALOGI("Starting SocketComm");
-    mSocketComm = std::make_unique<SocketComm>(this);
-    mSocketComm->start();
-
-    if (isInEmulator()) {
-        ALOGI("Starting PipeComm");
-        mPipeComm = std::make_unique<PipeComm>(this);
-        mPipeComm->start();
-    }
-}
-
-VehicleEmulator::~VehicleEmulator() {
-    mSocketComm->stop();
-    if (mPipeComm) {
-        mPipeComm->stop();
-    }
-}
-
-/**
- * This is called by the HAL when a property changes. We need to notify our clients that it has
- * changed.
- */
-void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) {
-    vhal_proto::EmulatorMessage msg;
-    vhal_proto::VehiclePropValue* val = msg.add_value();
-    populateProtoVehiclePropValue(val, &propValue);
-    msg.set_status(vhal_proto::RESULT_OK);
-    msg.set_msg_type(vhal_proto::SET_PROPERTY_ASYNC);
-
-    mSocketComm->sendMessage(msg);
-    if (mPipeComm) {
-        mPipeComm->sendMessage(msg);
-    }
-}
-
-void VehicleEmulator::doGetConfig(VehicleEmulator::EmulatorMessage const& rxMsg,
-                                  VehicleEmulator::EmulatorMessage& respMsg) {
-    std::vector<VehiclePropConfig> configs = mHal->listProperties();
-    vhal_proto::VehiclePropGet getProp = rxMsg.prop(0);
-
-    respMsg.set_msg_type(vhal_proto::GET_CONFIG_RESP);
-    respMsg.set_status(vhal_proto::ERROR_INVALID_PROPERTY);
-
-    for (auto& config : configs) {
-        // Find the config we are looking for
-        if (config.prop == getProp.prop()) {
-            vhal_proto::VehiclePropConfig* protoCfg = respMsg.add_config();
-            populateProtoVehicleConfig(protoCfg, config);
-            respMsg.set_status(vhal_proto::RESULT_OK);
-            break;
-        }
-    }
-}
-
-void VehicleEmulator::doGetConfigAll(VehicleEmulator::EmulatorMessage const& /* rxMsg */,
-                                     VehicleEmulator::EmulatorMessage& respMsg) {
-    std::vector<VehiclePropConfig> configs = mHal->listProperties();
-
-    respMsg.set_msg_type(vhal_proto::GET_CONFIG_ALL_RESP);
-    respMsg.set_status(vhal_proto::RESULT_OK);
-
-    for (auto& config : configs) {
-        vhal_proto::VehiclePropConfig* protoCfg = respMsg.add_config();
-        populateProtoVehicleConfig(protoCfg, config);
-    }
-}
-
-void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage const& rxMsg,
-                                    VehicleEmulator::EmulatorMessage& respMsg) {
-    int32_t areaId = 0;
-    vhal_proto::VehiclePropGet getProp = rxMsg.prop(0);
-    int32_t propId = getProp.prop();
-    vhal_proto::Status status = vhal_proto::ERROR_INVALID_PROPERTY;
-
-    respMsg.set_msg_type(vhal_proto::GET_PROPERTY_RESP);
-
-    if (getProp.has_area_id()) {
-        areaId = getProp.area_id();
-    }
-
-    {
-        VehiclePropValue request = {
-                .areaId = areaId,
-                .prop = propId,
-        };
-        StatusCode halStatus;
-        auto val = mHal->get(request, &halStatus);
-        if (val != nullptr) {
-            vhal_proto::VehiclePropValue* protoVal = respMsg.add_value();
-            populateProtoVehiclePropValue(protoVal, val.get());
-            status = vhal_proto::RESULT_OK;
-        }
-    }
-
-    respMsg.set_status(status);
-}
-
-void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage const& /* rxMsg */,
-                                       VehicleEmulator::EmulatorMessage& respMsg) {
-    respMsg.set_msg_type(vhal_proto::GET_PROPERTY_ALL_RESP);
-    respMsg.set_status(vhal_proto::RESULT_OK);
-
-    {
-        for (const auto& prop : mHal->getAllProperties()) {
-            vhal_proto::VehiclePropValue* protoVal = respMsg.add_value();
-            populateProtoVehiclePropValue(protoVal, &prop);
-        }
-    }
-}
-
-void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage const& rxMsg,
-                                    VehicleEmulator::EmulatorMessage& respMsg) {
-    vhal_proto::VehiclePropValue protoVal = rxMsg.value(0);
-    VehiclePropValue val = {
-            .timestamp = elapsedRealtimeNano(),
-            .areaId = protoVal.area_id(),
-            .prop = protoVal.prop(),
-            .status = (VehiclePropertyStatus)protoVal.status(),
-    };
-
-    respMsg.set_msg_type(vhal_proto::SET_PROPERTY_RESP);
-
-    // Copy value data if it is set.  This automatically handles complex data types if needed.
-    if (protoVal.has_string_value()) {
-        val.value.stringValue = protoVal.string_value().c_str();
-    }
-
-    if (protoVal.has_bytes_value()) {
-        val.value.bytes = std::vector<uint8_t> { protoVal.bytes_value().begin(),
-                                                 protoVal.bytes_value().end() };
-    }
-
-    if (protoVal.int32_values_size() > 0) {
-        val.value.int32Values = std::vector<int32_t> { protoVal.int32_values().begin(),
-                                                       protoVal.int32_values().end() };
-    }
-
-    if (protoVal.int64_values_size() > 0) {
-        val.value.int64Values = std::vector<int64_t> { protoVal.int64_values().begin(),
-                                                       protoVal.int64_values().end() };
-    }
-
-    if (protoVal.float_values_size() > 0) {
-        val.value.floatValues = std::vector<float> { protoVal.float_values().begin(),
-                                                     protoVal.float_values().end() };
-    }
-
-    bool halRes = mHal->setPropertyFromVehicle(val);
-    respMsg.set_status(halRes ? vhal_proto::RESULT_OK : vhal_proto::ERROR_INVALID_PROPERTY);
-}
-
-void VehicleEmulator::processMessage(vhal_proto::EmulatorMessage const& rxMsg,
-                                     vhal_proto::EmulatorMessage& respMsg) {
-    switch (rxMsg.msg_type()) {
-        case vhal_proto::GET_CONFIG_CMD:
-            doGetConfig(rxMsg, respMsg);
-            break;
-        case vhal_proto::GET_CONFIG_ALL_CMD:
-            doGetConfigAll(rxMsg, respMsg);
-            break;
-        case vhal_proto::GET_PROPERTY_CMD:
-            doGetProperty(rxMsg, respMsg);
-            break;
-        case vhal_proto::GET_PROPERTY_ALL_CMD:
-            doGetPropertyAll(rxMsg, respMsg);
-            break;
-        case vhal_proto::SET_PROPERTY_CMD:
-            doSetProperty(rxMsg, respMsg);
-            break;
-        default:
-            ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
-            respMsg.set_status(vhal_proto::ERROR_UNIMPLEMENTED_CMD);
-            break;
-    }
-}
-
-void VehicleEmulator::populateProtoVehicleConfig(vhal_proto::VehiclePropConfig* protoCfg,
-                                                 const VehiclePropConfig& cfg) {
-    return proto_msg_converter::toProto(protoCfg, cfg);
-}
-
-void VehicleEmulator::populateProtoVehiclePropValue(vhal_proto::VehiclePropValue* protoVal,
-                                                    const VehiclePropValue* val) {
-    return proto_msg_converter::toProto(protoVal, *val);
-}
-
-bool isInEmulator() {
-    return android::base::GetBoolProperty("ro.boot.qemu", false);
-}
-
-}  // impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
deleted file mode 100644
index 434d79b..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
+++ /dev/null
@@ -1,109 +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 android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
-
-#include <log/log.h>
-#include <memory>
-#include <thread>
-#include <vector>
-
-#include "vhal_v2_0/VehicleHal.h"
-
-#include "CommConn.h"
-#include "PipeComm.h"
-#include "SocketComm.h"
-#include "VehicleHalProto.pb.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-class VehicleEmulator;  // Forward declaration.
-
-/** Extension of VehicleHal that used by VehicleEmulator. */
-class EmulatedVehicleHalIface : public VehicleHal {
-public:
-    virtual bool setPropertyFromVehicle(const VehiclePropValue& propValue) = 0;
-    virtual std::vector<VehiclePropValue> getAllProperties() const = 0;
-
-    void registerEmulator(VehicleEmulator* emulator) {
-        ALOGI("%s, emulator: %p", __func__, emulator);
-        std::lock_guard<std::mutex> g(mEmulatorLock);
-        mEmulator = emulator;
-    }
-
-protected:
-    VehicleEmulator* getEmulatorOrDie() {
-        std::lock_guard<std::mutex> g(mEmulatorLock);
-        if (mEmulator == nullptr) abort();
-        return mEmulator;
-    }
-
-private:
-    mutable std::mutex mEmulatorLock;
-    VehicleEmulator* mEmulator;
-};
-
-/**
- * Emulates vehicle by providing controlling interface from host side either through ADB or Pipe.
- */
-class VehicleEmulator : public MessageProcessor {
-   public:
-    VehicleEmulator(EmulatedVehicleHalIface* hal);
-    virtual ~VehicleEmulator();
-
-    void doSetValueFromClient(const VehiclePropValue& propValue);
-    void processMessage(vhal_proto::EmulatorMessage const& rxMsg,
-                        vhal_proto::EmulatorMessage& respMsg) override;
-
-   private:
-    friend class ConnectionThread;
-    using EmulatorMessage = vhal_proto::EmulatorMessage;
-
-    void doGetConfig(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
-    void doGetConfigAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
-    void doGetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
-    void doGetPropertyAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
-    void doSetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
-    void populateProtoVehicleConfig(vhal_proto::VehiclePropConfig* protoCfg,
-                                    const VehiclePropConfig& cfg);
-    void populateProtoVehiclePropValue(vhal_proto::VehiclePropValue* protoVal,
-                                       const VehiclePropValue* val);
-
-private:
-    EmulatedVehicleHalIface* mHal;
-    std::unique_ptr<SocketComm> mSocketComm;
-    std::unique_ptr<PipeComm> mPipeComm;
-};
-
-// determine if it's running inside Android Emulator
-bool isInEmulator();
-
-}  // impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-#endif // android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
index 25ffc6d..bafd170 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
@@ -18,7 +18,13 @@
 
 #include <android-base/logging.h>
 
-namespace android::hardware::automotive::vehicle::V2_0::impl {
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
 
 void VehicleHalClient::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
     if (!mPropCallback) {
@@ -36,4 +42,10 @@
     mPropCallback = std::move(callback);
 }
 
-}  // namespace android::hardware::automotive::vehicle::V2_0::impl
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
index 81dfca1..2473f19 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
@@ -18,7 +18,13 @@
 
 #include <vhal_v2_0/VehicleClient.h>
 
-namespace android::hardware::automotive::vehicle::V2_0::impl {
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
 
 // The common client operations that may be used by both native and
 // virtualized VHAL clients.
@@ -40,4 +46,10 @@
     PropertyCallBackType mPropCallback;
 };
 
-}  // namespace android::hardware::automotive::vehicle::V2_0::impl
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
deleted file mode 100644
index 57dd7d4..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
+++ /dev/null
@@ -1,340 +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.
- */
-
-#define LOG_TAG "VehicleHalServer"
-
-#include "VehicleHalServer.h"
-
-#include <fstream>
-
-#include <android-base/logging.h>
-#include <utils/SystemClock.h>
-
-#include "DefaultConfig.h"
-#include "JsonFakeValueGenerator.h"
-#include "LinearFakeValueGenerator.h"
-#include "Obd2SensorStore.h"
-
-namespace android::hardware::automotive::vehicle::V2_0::impl {
-
-static bool isDiagnosticProperty(VehiclePropConfig propConfig) {
-    switch (propConfig.prop) {
-        case OBD2_LIVE_FRAME:
-        case OBD2_FREEZE_FRAME:
-        case OBD2_FREEZE_FRAME_CLEAR:
-        case OBD2_FREEZE_FRAME_INFO:
-            return true;
-    }
-    return false;
-}
-
-VehicleHalServer::VehicleHalServer() {
-    constexpr bool shouldUpdateStatus = true;
-
-    for (auto& it : kVehicleProperties) {
-        VehiclePropConfig cfg = it.config;
-
-        mServerSidePropStore.registerProperty(cfg);
-
-        if (isDiagnosticProperty(cfg)) {
-            continue;
-        }
-
-        // A global property will have only a single area
-        int32_t numAreas = isGlobalProp(cfg.prop) ? 1 : cfg.areaConfigs.size();
-
-        for (int i = 0; i < numAreas; i++) {
-            int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId;
-
-            // Create a separate instance for each individual zone
-            VehiclePropValue prop = {
-                    .areaId = curArea,
-                    .prop = cfg.prop,
-            };
-
-            if (it.initialAreaValues.empty()) {
-                prop.value = it.initialValue;
-            } else if (auto valueForAreaIt = it.initialAreaValues.find(curArea);
-                       valueForAreaIt != it.initialAreaValues.end()) {
-                prop.value = valueForAreaIt->second;
-            } else {
-                LOG(WARNING) << __func__ << " failed to get default value for"
-                             << " prop 0x" << std::hex << cfg.prop << " area 0x" << std::hex
-                             << curArea;
-                prop.status = VehiclePropertyStatus::UNAVAILABLE;
-            }
-
-            mServerSidePropStore.writeValue(prop, shouldUpdateStatus);
-        }
-    }
-}
-
-void VehicleHalServer::sendAllValuesToClient() {
-    constexpr bool update_status = true;
-    auto values = mServerSidePropStore.readAllValues();
-    for (const auto& value : values) {
-        onPropertyValueFromCar(value, update_status);
-    }
-}
-
-GeneratorHub* VehicleHalServer::getGenerator() {
-    return &mGeneratorHub;
-}
-
-VehiclePropValuePool* VehicleHalServer::getValuePool() const {
-    if (!mValuePool) {
-        LOG(WARNING) << __func__ << ": Value pool not set!";
-    }
-    return mValuePool;
-}
-
-void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
-    if (!valuePool) {
-        LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
-    }
-    mValuePool = valuePool;
-}
-
-void VehicleHalServer::onFakeValueGenerated(const VehiclePropValue& value) {
-    constexpr bool updateStatus = true;
-    LOG(DEBUG) << __func__ << ": " << toString(value);
-    auto updatedPropValue = getValuePool()->obtain(value);
-    if (updatedPropValue) {
-        updatedPropValue->timestamp = value.timestamp;
-        updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
-        mServerSidePropStore.writeValue(*updatedPropValue, updateStatus);
-        onPropertyValueFromCar(*updatedPropValue, updateStatus);
-    }
-}
-
-std::vector<VehiclePropConfig> VehicleHalServer::onGetAllPropertyConfig() const {
-    return mServerSidePropStore.getAllConfigs();
-}
-
-StatusCode VehicleHalServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
-    constexpr bool updateStatus = true;
-
-    LOG(INFO) << __func__;
-    const auto& v = request.value;
-    if (!v.int32Values.size()) {
-        LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
-        return StatusCode::INVALID_ARG;
-    }
-
-    FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
-
-    switch (command) {
-        case FakeDataCommand::StartLinear: {
-            LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
-            if (v.int32Values.size() < 2) {
-                LOG(ERROR) << __func__ << ": expected property ID in int32Values";
-                return StatusCode::INVALID_ARG;
-            }
-            if (!v.int64Values.size()) {
-                LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
-                return StatusCode::INVALID_ARG;
-            }
-            if (v.floatValues.size() < 3) {
-                LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
-                           << v.floatValues.size();
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = v.int32Values[1];
-            getGenerator()->registerGenerator(cookie,
-                                              std::make_unique<LinearFakeValueGenerator>(request));
-            break;
-        }
-        case FakeDataCommand::StartJson: {
-            LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
-            if (v.stringValue.empty()) {
-                LOG(ERROR) << __func__ << ": path to JSON file is missing";
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = std::hash<std::string>()(v.stringValue);
-            getGenerator()->registerGenerator(cookie,
-                                              std::make_unique<JsonFakeValueGenerator>(request));
-            break;
-        }
-        case FakeDataCommand::StopLinear: {
-            LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
-            if (v.int32Values.size() < 2) {
-                LOG(ERROR) << __func__ << ": expected property ID in int32Values";
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = v.int32Values[1];
-            getGenerator()->unregisterGenerator(cookie);
-            break;
-        }
-        case FakeDataCommand::StopJson: {
-            LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
-            if (v.stringValue.empty()) {
-                LOG(ERROR) << __func__ << ": path to JSON file is missing";
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = std::hash<std::string>()(v.stringValue);
-            getGenerator()->unregisterGenerator(cookie);
-            break;
-        }
-        case FakeDataCommand::KeyPress: {
-            LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
-            int32_t keyCode = request.value.int32Values[2];
-            int32_t display = request.value.int32Values[3];
-            // Send back to HAL
-            onPropertyValueFromCar(
-                    *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
-                    updateStatus);
-            onPropertyValueFromCar(
-                    *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
-                    updateStatus);
-            break;
-        }
-        default: {
-            LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
-            return StatusCode::INVALID_ARG;
-        }
-    }
-    return StatusCode::OK;
-}
-
-VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createApPowerStateReq(
-        VehicleApPowerStateReq state, int32_t param) {
-    auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
-    req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
-    req->areaId = 0;
-    req->timestamp = elapsedRealtimeNano();
-    req->status = VehiclePropertyStatus::AVAILABLE;
-    req->value.int32Values[0] = toInt(state);
-    req->value.int32Values[1] = param;
-    return req;
-}
-
-VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createHwInputKeyProp(
-        VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
-    auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
-    keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
-    keyEvent->areaId = 0;
-    keyEvent->timestamp = elapsedRealtimeNano();
-    keyEvent->status = VehiclePropertyStatus::AVAILABLE;
-    keyEvent->value.int32Values[0] = toInt(action);
-    keyEvent->value.int32Values[1] = keyCode;
-    keyEvent->value.int32Values[2] = targetDisplay;
-    return keyEvent;
-}
-
-StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
-    LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
-
-    // Some properties need to be treated non-trivially
-    switch (value.prop) {
-        case kGenerateFakeDataControllingProperty:
-            return handleGenerateFakeDataRequest(value);
-
-        // set the value from vehicle side, used in end to end test.
-        case kSetIntPropertyFromVehicleForTest: {
-            auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
-            updatedPropValue->prop = value.value.int32Values[0];
-            updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
-            updatedPropValue->timestamp = value.value.int64Values[0];
-            updatedPropValue->areaId = value.areaId;
-            onPropertyValueFromCar(*updatedPropValue, updateStatus);
-            return StatusCode::OK;
-        }
-        case kSetFloatPropertyFromVehicleForTest: {
-            auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
-            updatedPropValue->prop = value.value.int32Values[0];
-            updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
-            updatedPropValue->timestamp = value.value.int64Values[0];
-            updatedPropValue->areaId = value.areaId;
-            onPropertyValueFromCar(*updatedPropValue, updateStatus);
-            return StatusCode::OK;
-        }
-        case kSetBooleanPropertyFromVehicleForTest: {
-            auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
-            updatedPropValue->prop = value.value.int32Values[1];
-            updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
-            updatedPropValue->timestamp = value.value.int64Values[0];
-            updatedPropValue->areaId = value.areaId;
-            onPropertyValueFromCar(*updatedPropValue, updateStatus);
-            return StatusCode::OK;
-        }
-
-        case AP_POWER_STATE_REPORT:
-            switch (value.value.int32Values[0]) {
-                case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
-                case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
-                case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
-                    // CPMS is in WAIT_FOR_VHAL state, simply move to ON
-                    // Send back to HAL
-                    // ALWAYS update status for generated property value
-                    onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
-                                           true /* updateStatus */);
-                    break;
-                case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
-                case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
-                    // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
-                    // Send back to HAL
-                    // ALWAYS update status for generated property value
-                    onPropertyValueFromCar(
-                            *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
-                            true /* updateStatus */);
-                    break;
-                case toInt(VehicleApPowerStateReport::ON):
-                case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
-                case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
-                    // Do nothing
-                    break;
-                default:
-                    // Unknown state
-                    break;
-            }
-            break;
-
-#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
-        case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
-        case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
-        case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE):
-        case VENDOR_CLUSTER_SWITCH_UI:
-        case VENDOR_CLUSTER_DISPLAY_STATE: {
-            auto updatedPropValue = createVehiclePropValue(getPropType(value.prop), 0);
-            updatedPropValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK);
-            if (isSystemProperty(value.prop)) {
-                updatedPropValue->prop |= toInt(VehiclePropertyGroup::VENDOR);
-            } else {
-                updatedPropValue->prop |= toInt(VehiclePropertyGroup::SYSTEM);
-            }
-            updatedPropValue->value = value.value;
-            updatedPropValue->timestamp = elapsedRealtimeNano();
-            updatedPropValue->areaId = value.areaId;
-            onPropertyValueFromCar(*updatedPropValue, updateStatus);
-            return StatusCode::OK;
-        }
-#endif  // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
-
-        default:
-            break;
-    }
-
-    // In the real vhal, the value will be sent to Car ECU.
-    // We just pretend it is done here and send back to HAL
-    auto updatedPropValue = getValuePool()->obtain(value);
-    updatedPropValue->timestamp = elapsedRealtimeNano();
-
-    mServerSidePropStore.writeValue(*updatedPropValue, updateStatus);
-    onPropertyValueFromCar(*updatedPropValue, updateStatus);
-    return StatusCode::OK;
-}
-
-}  // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
index be88cd9..1290f30 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,56 +14,32 @@
  * limitations under the License.
  */
 
+// This file is just used for soft migration from VehicleHalServer to DefaultVehicleHalServer.
+// The virtualized VHAL that uses VehichleHalServer is at a different repo and cannot be updated
+// together with this repo, so we need a soft migration. Once the rename is finished at the
+// virtualized VHAL side, this file would be removed.
+
 #pragma once
 
-#include <vhal_v2_0/VehicleObjectPool.h>
-#include <vhal_v2_0/VehiclePropertyStore.h>
-#include <vhal_v2_0/VehicleServer.h>
+#include "DefaultVehicleHalServer.h"
 
-#include "GeneratorHub.h"
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
 
-namespace android::hardware::automotive::vehicle::V2_0::impl {
+namespace impl {
 
-// This contains the common server operations that will be used by
-// both native and virtualized VHAL server. Notice that in the virtualized
-// scenario, the server may be run on a different OS than Android.
-class VehicleHalServer : public IVehicleServer {
+class VehicleHalServer : public DefaultVehicleHalServer {
   public:
-    VehicleHalServer();
-
-    void sendAllValuesToClient();
-
-    // Methods from IVehicleServer
-
-    std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;
-
-    StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
-
-    // Set the Property Value Pool used in this server
-    void setValuePool(VehiclePropValuePool* valuePool);
-
-  private:
-    using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
-
-    GeneratorHub* getGenerator();
-
-    VehiclePropValuePool* getValuePool() const;
-
-    void onFakeValueGenerated(const VehiclePropValue& value);
-
-    StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
-
-    VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
-
-    VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
-                                             int32_t targetDisplay);
-
-  private:
-    GeneratorHub mGeneratorHub{
-            std::bind(&VehicleHalServer::onFakeValueGenerated, this, std::placeholders::_1)};
-
-    VehiclePropValuePool* mValuePool{nullptr};
-    VehiclePropertyStore mServerSidePropStore;
+    VehicleHalServer() : DefaultVehicleHalServer(){};
 };
 
-}  // namespace android::hardware::automotive::vehicle::V2_0::impl
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
index 6e85ae9..3307bd6 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
@@ -24,6 +24,10 @@
 
 cc_library_static {
     name: "android.hardware.automotive.vehicle@2.0-libproto-native",
+    visibility: [
+        "//hardware/interfaces/automotive/vehicle/2.0/default:__subpackages__",
+        "//device/generic/car/emulator/vhal_v2_0:__subpackages__",
+    ],
     vendor: true,
     host_supported: true,
     proto: {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
index 4902a5d..58daca6 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
@@ -32,6 +32,8 @@
     SET_PROPERTY_CMD                    = 8;
     SET_PROPERTY_RESP                   = 9;
     SET_PROPERTY_ASYNC                  = 10;
+    DEBUG_CMD                           = 11;
+    DEBUG_RESP                          = 12;
 }
 enum Status {
     RESULT_OK                           = 0;
@@ -98,9 +100,11 @@
 };
 
 message EmulatorMessage {
-    required MsgType           msg_type = 1;
-    optional Status            status   = 2;    // Only for RESP messages
-    repeated VehiclePropGet    prop     = 3;    // Provided for getConfig, getProperty commands
-    repeated VehiclePropConfig config   = 4;
-    repeated VehiclePropValue  value    = 5;
+    required MsgType           msg_type       = 1;
+    optional Status            status         = 2; // Only for RESP messages
+    repeated VehiclePropGet    prop           = 3; // Provided for getConfig, getProperty commands
+    repeated VehiclePropConfig config         = 4;
+    repeated VehiclePropValue  value          = 5;
+    repeated string            debug_commands = 6; // Required for debug command
+    optional string            debug_result   = 7; // Required for debug RESP messages
 };
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.cpp
deleted file mode 100644
index cf1a002..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "qemu_pipe.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <android-base/file.h>
-
-using android::base::ReadFully;
-using android::base::WriteFully;
-
-// Define QEMU_PIPE_DEBUG if you want to print error messages when an error
-// occurs during pipe operations. The macro should simply take a printf-style
-// formatting string followed by optional arguments.
-#ifndef QEMU_PIPE_DEBUG
-#define QEMU_PIPE_DEBUG(...) (void)0
-#endif
-
-int qemu_pipe_open(const char* pipeName) {
-    if (!pipeName) {
-        errno = EINVAL;
-        return -1;
-    }
-
-    int fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR));
-    if (fd < 0) {
-        QEMU_PIPE_DEBUG("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__, strerror(errno));
-        return -1;
-    }
-
-    // Write the pipe name, *including* the trailing zero which is necessary.
-    size_t pipeNameLen = strlen(pipeName);
-    if (WriteFully(fd, pipeName, pipeNameLen + 1U)) {
-        return fd;
-    }
-
-    // now, add 'pipe:' prefix and try again
-    // Note: host side will wait for the trailing '\0' to start
-    // service lookup.
-    const char pipe_prefix[] = "pipe:";
-    if (WriteFully(fd, pipe_prefix, strlen(pipe_prefix)) &&
-        WriteFully(fd, pipeName, pipeNameLen + 1U)) {
-        return fd;
-    }
-    QEMU_PIPE_DEBUG("%s: Could not write to %s pipe service: %s", __FUNCTION__, pipeName,
-                    strerror(errno));
-    close(fd);
-    return -1;
-}
-
-int qemu_pipe_frame_send(int fd, const void* buff, size_t len) {
-    char header[5];
-    snprintf(header, sizeof(header), "%04zx", len);
-    if (!WriteFully(fd, header, 4)) {
-        QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno));
-        return -1;
-    }
-    if (!WriteFully(fd, buff, len)) {
-        QEMU_PIPE_DEBUG("Can't write qemud frame payload: %s", strerror(errno));
-        return -1;
-    }
-    return 0;
-}
-
-int qemu_pipe_frame_recv(int fd, void* buff, size_t len) {
-    char header[5];
-    if (!ReadFully(fd, header, 4)) {
-        QEMU_PIPE_DEBUG("Can't read qemud frame header: %s", strerror(errno));
-        return -1;
-    }
-    header[4] = '\0';
-    size_t size;
-    if (sscanf(header, "%04zx", &size) != 1) {
-        QEMU_PIPE_DEBUG("Malformed qemud frame header: [%.*s]", 4, header);
-        return -1;
-    }
-    if (size > len) {
-        QEMU_PIPE_DEBUG("Oversized qemud frame (% bytes, expected <= %)", size, len);
-        return -1;
-    }
-    if (!ReadFully(fd, buff, size)) {
-        QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s", strerror(errno));
-        return -1;
-    }
-    return size;
-}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.h
deleted file mode 100644
index 0987498..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_CORE_INCLUDE_QEMU_PIPE_H
-#define ANDROID_CORE_INCLUDE_QEMU_PIPE_H
-
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-// Try to open a new Qemu fast-pipe. This function returns a file descriptor
-// that can be used to communicate with a named service managed by the
-// emulator.
-//
-// This file descriptor can be used as a standard pipe/socket descriptor.
-//
-// 'pipeName' is the name of the emulator service you want to connect to,
-// and should begin with 'pipe:' (e.g. 'pipe:camera' or 'pipe:opengles').
-// For backward compatibility, the 'pipe:' prefix can be omitted, and in
-// that case, qemu_pipe_open will add it for you.
-
-// On success, return a valid file descriptor, or -1/errno on failure. E.g.:
-//
-// EINVAL  -> unknown/unsupported pipeName
-// ENOSYS  -> fast pipes not available in this system.
-//
-// ENOSYS should never happen, except if you're trying to run within a
-// misconfigured emulator.
-//
-// You should be able to open several pipes to the same pipe service,
-// except for a few special cases (e.g. GSM modem), where EBUSY will be
-// returned if more than one client tries to connect to it.
-int qemu_pipe_open(const char* pipeName);
-
-// Send a framed message |buff| of |len| bytes through the |fd| descriptor.
-// This really adds a 4-hexchar prefix describing the payload size.
-// Returns 0 on success, and -1 on error.
-int qemu_pipe_frame_send(int fd, const void* buff, size_t len);
-
-// Read a frame message from |fd|, and store it into |buff| of |len| bytes.
-// If the framed message is larger than |len|, then this returns -1 and the
-// content is lost. Otherwise, this returns the size of the message. NOTE:
-// empty messages are possible in a framed wire protocol and do not mean
-// end-of-stream.
-int qemu_pipe_frame_recv(int fd, void* buff, size_t len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ANDROID_CORE_INCLUDE_QEMU_PIPE_H */
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/Android.bp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/Android.bp
new file mode 100644
index 0000000..a0bcc6c
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // 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"],
+}
+
+filegroup {
+    name: "vhal_test_json",
+    srcs: ["prop.json"],
+}
+
+filegroup {
+    name: "vhal_test_override_json",
+    srcs: ["override/*"],
+}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp
new file mode 100644
index 0000000..e3c8dd6
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp
@@ -0,0 +1,1394 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/file.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <sys/mman.h>
+#include <vhal_v2_0/ConcurrentQueue.h>
+#include <vhal_v2_0/DefaultConfig.h>
+#include <vhal_v2_0/DefaultVehicleConnector.h>
+#include <vhal_v2_0/DefaultVehicleHal.h>
+#include <vhal_v2_0/PropertyUtils.h>
+#include <vhal_v2_0/VehicleObjectPool.h>
+#include <vhal_v2_0/VehiclePropertyStore.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+namespace impl {
+
+class DefaultVhalImplTestHelper {
+  public:
+    DefaultVhalImplTestHelper(DefaultVehicleHalServer* server) { mServer = server; }
+
+    void overrideProperties(const char* overrideDir) {
+        mServer->overrideProperties(overrideDir);
+    }
+
+  private:
+    DefaultVehicleHalServer* mServer;
+};
+
+}  // namespace impl
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+namespace {
+
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::automotive::vehicle::V2_0::FuelType;
+using ::android::hardware::automotive::vehicle::V2_0::recyclable_ptr;
+using ::android::hardware::automotive::vehicle::V2_0::StatusCode;
+using ::android::hardware::automotive::vehicle::V2_0::VehicleHwKeyInputAction;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropConfig;
+using ::android::hardware::automotive::vehicle::V2_0::VehicleProperty;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropertyStatus;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropertyStore;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropValue;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropValuePool;
+using ::android::hardware::automotive::vehicle::V2_0::impl::DefaultVehicleConnector;
+using ::android::hardware::automotive::vehicle::V2_0::impl::DefaultVehicleHal;
+using ::android::hardware::automotive::vehicle::V2_0::impl::DefaultVhalImplTestHelper;
+using ::android::hardware::automotive::vehicle::V2_0::impl::DOOR_1_LEFT;
+using ::android::hardware::automotive::vehicle::V2_0::impl::DOOR_1_RIGHT;
+using ::android::hardware::automotive::vehicle::V2_0::impl::HVAC_ALL;
+using ::android::hardware::automotive::vehicle::V2_0::impl::HVAC_LEFT;
+using ::android::hardware::automotive::vehicle::V2_0::impl::HVAC_RIGHT;
+using ::android::hardware::automotive::vehicle::V2_0::impl::kMixedTypePropertyForTest;
+using ::android::hardware::automotive::vehicle::V2_0::impl::OBD2_FREEZE_FRAME;
+using ::android::hardware::automotive::vehicle::V2_0::impl::OBD2_FREEZE_FRAME_CLEAR;
+using ::android::hardware::automotive::vehicle::V2_0::impl::OBD2_FREEZE_FRAME_INFO;
+using ::android::hardware::automotive::vehicle::V2_0::impl::OBD2_LIVE_FRAME;
+
+using ::testing::HasSubstr;
+
+using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
+
+// The maximum length of property ID in string.
+const size_t MAX_PROP_ID_LENGTH = 100;
+
+class DefaultVhalImplTest : public ::testing::Test {
+  public:
+    ~DefaultVhalImplTest() {
+        mEventQueue.deactivate();
+        mHeartBeatQueue.deactivate();
+        // Destroy mHal before destroying its dependencies.
+        mHal.reset();
+        mConnector.reset();
+        mPropStore.reset();
+    }
+
+  protected:
+    void SetUp() override {
+        mPropStore.reset(new VehiclePropertyStore);
+        mConnector.reset(new DefaultVehicleConnector);
+        mConnector->setValuePool(&mValueObjectPool);
+        mHal.reset(new DefaultVehicleHal(mPropStore.get(), mConnector.get()));
+        initHal();
+    }
+
+    void initHal() {
+        mHal->init(&mValueObjectPool,
+                   std::bind(&DefaultVhalImplTest::onHalEvent, this, std::placeholders::_1),
+                   std::bind(&DefaultVhalImplTest::onHalPropertySetError, this,
+                             std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+    }
+
+  protected:
+    std::unique_ptr<DefaultVehicleHal> mHal;
+    std::unique_ptr<DefaultVehicleConnector> mConnector;
+    std::unique_ptr<VehiclePropertyStore> mPropStore;
+    VehiclePropValuePool mValueObjectPool;
+    android::ConcurrentQueue<VehiclePropValuePtr> mEventQueue;
+    android::ConcurrentQueue<VehiclePropValuePtr> mHeartBeatQueue;
+
+  private:
+    void onHalEvent(VehiclePropValuePtr v) {
+        if (v->prop != toInt(VehicleProperty::VHAL_HEARTBEAT)) {
+            // Ignore heartbeat properties.
+            mEventQueue.push(std::move(v));
+        } else {
+            mHeartBeatQueue.push(std::move(v));
+        }
+    }
+
+    void onHalPropertySetError(StatusCode /*errorCode*/, int32_t /*property*/, int32_t /*areaId*/) {
+    }
+};
+
+TEST_F(DefaultVhalImplTest, testListProperties) {
+    std::vector<VehiclePropConfig> configs = mHal->listProperties();
+
+    EXPECT_EQ((size_t)121, configs.size());
+}
+
+TEST_F(DefaultVhalImplTest, testGetDefaultPropertyFloat) {
+    VehiclePropValue value;
+    StatusCode status;
+    value.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
+
+    auto gotValue = mHal->get(value, &status);
+
+    EXPECT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((unsigned int)1, gotValue->value.floatValues.size());
+    EXPECT_EQ(15000.0f, gotValue->value.floatValues[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testGetDefaultPropertyEnum) {
+    VehiclePropValue value;
+    StatusCode status;
+    value.prop = toInt(VehicleProperty::INFO_FUEL_TYPE);
+
+    auto gotValue = mHal->get(value, &status);
+
+    EXPECT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((unsigned int)1, gotValue->value.int32Values.size());
+    EXPECT_EQ((int)FuelType::FUEL_TYPE_UNLEADED, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testGetDefaultPropertyInt) {
+    VehiclePropValue value;
+    StatusCode status;
+    value.prop = toInt(VehicleProperty::INFO_MODEL_YEAR);
+
+    auto gotValue = mHal->get(value, &status);
+
+    EXPECT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((unsigned int)1, gotValue->value.int32Values.size());
+    EXPECT_EQ(2020, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testGetDefaultPropertyString) {
+    VehiclePropValue value;
+    StatusCode status;
+    value.prop = toInt(VehicleProperty::INFO_MAKE);
+
+    auto gotValue = mHal->get(value, &status);
+
+    EXPECT_EQ(StatusCode::OK, status);
+    EXPECT_EQ("Toy Vehicle", gotValue->value.stringValue);
+}
+
+TEST_F(DefaultVhalImplTest, testGetUnknownProperty) {
+    VehiclePropValue value;
+    StatusCode status;
+    value.prop = 0;
+
+    auto gotValue = mHal->get(value, &status);
+
+    EXPECT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+TEST_F(DefaultVhalImplTest, testSetFloat) {
+    VehiclePropValue value;
+    value.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
+    value.value.floatValues.resize(1);
+    value.value.floatValues[0] = 1.0f;
+
+    StatusCode status = mHal->set(value);
+    ASSERT_EQ(StatusCode::OK, status);
+
+    auto gotValue = mHal->get(value, &status);
+    EXPECT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((unsigned int)1, gotValue->value.floatValues.size());
+    EXPECT_EQ(1.0f, gotValue->value.floatValues[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testSetEnum) {
+    VehiclePropValue value;
+    value.prop = toInt(VehicleProperty::INFO_FUEL_TYPE);
+    value.value.int32Values.resize(1);
+    value.value.int32Values[0] = (int)FuelType::FUEL_TYPE_LEADED;
+
+    StatusCode status = mHal->set(value);
+    ASSERT_EQ(StatusCode::OK, status);
+
+    auto gotValue = mHal->get(value, &status);
+    EXPECT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((unsigned int)1, gotValue->value.int32Values.size());
+    EXPECT_EQ((int)FuelType::FUEL_TYPE_LEADED, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testSetInt) {
+    VehiclePropValue value;
+    value.prop = toInt(VehicleProperty::INFO_MODEL_YEAR);
+    value.value.int32Values.resize(1);
+    value.value.int32Values[0] = 2021;
+
+    StatusCode status = mHal->set(value);
+    EXPECT_EQ(StatusCode::OK, status);
+
+    auto gotValue = mHal->get(value, &status);
+    EXPECT_EQ(StatusCode::OK, status);
+    EXPECT_EQ((unsigned int)1, gotValue->value.int32Values.size());
+    EXPECT_EQ(2021, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testSetString) {
+    VehiclePropValue value;
+    value.prop = toInt(VehicleProperty::INFO_MAKE);
+    value.value.stringValue = "My Vehicle";
+
+    StatusCode status = mHal->set(value);
+    ASSERT_EQ(StatusCode::OK, status);
+
+    auto gotValue = mHal->get(value, &status);
+    EXPECT_EQ(StatusCode::OK, status);
+    EXPECT_EQ("My Vehicle", gotValue->value.stringValue);
+}
+
+TEST_F(DefaultVhalImplTest, testSetMixed) {
+    VehiclePropValue value;
+    value.prop = kMixedTypePropertyForTest;
+    // mixed prop.
+    // .configArray = {1, 1, 0, 2, 0, 0, 1, 0, 0}
+    // 1 string, 1 int, 0 bool, 2 ints, 0 int64, 0 int64s, 1 float, 0 floats, 0 bytes
+    value.value.stringValue = "test";
+    value.value.int32Values.resize(3);
+    value.value.int32Values[0] = 1;
+    value.value.int32Values[1] = 2;
+    value.value.int32Values[2] = 3;
+    value.value.floatValues.resize(1);
+    value.value.floatValues[0] = 1.0f;
+
+    StatusCode status = mHal->set(value);
+    ASSERT_EQ(StatusCode::OK, status);
+
+    auto gotValue = mHal->get(value, &status);
+    EXPECT_EQ(StatusCode::OK, status);
+    EXPECT_EQ("test", gotValue->value.stringValue);
+    ASSERT_EQ((size_t)3, gotValue->value.int32Values.size());
+    EXPECT_EQ(1, gotValue->value.int32Values[0]);
+    EXPECT_EQ(2, gotValue->value.int32Values[1]);
+    EXPECT_EQ(3, gotValue->value.int32Values[2]);
+    ASSERT_EQ((size_t)1, gotValue->value.floatValues.size());
+    EXPECT_EQ(1.0f, gotValue->value.floatValues[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testSetUnknownProperty) {
+    VehiclePropValue value;
+    value.prop = 0;
+
+    EXPECT_EQ(StatusCode::INVALID_ARG, mHal->set(value));
+}
+
+TEST_F(DefaultVhalImplTest, testSetStatusNotAllowed) {
+    VehiclePropValue value;
+    value.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
+    value.status = VehiclePropertyStatus::UNAVAILABLE;
+    value.value.floatValues.resize(1);
+    value.value.floatValues[0] = 1.0f;
+
+    StatusCode status = mHal->set(value);
+
+    EXPECT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+TEST_F(DefaultVhalImplTest, testSubscribe) {
+    // Clear existing events.
+    mEventQueue.flush();
+
+    auto status = mHal->subscribe(toInt(VehicleProperty::PERF_VEHICLE_SPEED), 10);
+
+    ASSERT_EQ(StatusCode::OK, status);
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+    // Modify the speed after 0.5 seconds.
+    VehiclePropValue value;
+    value.prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+    value.value.floatValues.resize(1);
+    value.value.floatValues[0] = 1.0f;
+    ASSERT_EQ(StatusCode::OK, mHal->set(value));
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+    auto events = mEventQueue.flush();
+    ASSERT_LE((size_t)10, events.size());
+
+    // The first event should be the default value.
+    ASSERT_EQ((size_t)1, events[0]->value.floatValues.size());
+    EXPECT_EQ(0.0f, events[0]->value.floatValues[0]);
+    // The last event should be the value after update.
+    ASSERT_EQ((size_t)1, events[events.size() - 1]->value.floatValues.size());
+    EXPECT_EQ(1.0f, events[events.size() - 1]->value.floatValues[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testSubscribeInvalidProp) {
+    EXPECT_EQ(StatusCode::INVALID_ARG, mHal->subscribe(toInt(VehicleProperty::INFO_MAKE), 10));
+}
+
+TEST_F(DefaultVhalImplTest, testSubscribeSampleRateOutOfRange) {
+    EXPECT_EQ(StatusCode::INVALID_ARG,
+              mHal->subscribe(toInt(VehicleProperty::PERF_VEHICLE_SPEED), 10.1));
+    EXPECT_EQ(StatusCode::INVALID_ARG,
+              mHal->subscribe(toInt(VehicleProperty::PERF_VEHICLE_SPEED), 0.5));
+}
+
+TEST_F(DefaultVhalImplTest, testUnsubscribe) {
+    auto status = mHal->subscribe(toInt(VehicleProperty::PERF_VEHICLE_SPEED), 10);
+    ASSERT_EQ(StatusCode::OK, status);
+
+    // Wait for 0.5 seconds to generate some events.
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+    status = mHal->unsubscribe(toInt(VehicleProperty::PERF_VEHICLE_SPEED));
+    ASSERT_EQ(StatusCode::OK, status);
+
+    // Clear all the events.
+    mEventQueue.flush();
+
+    // Wait for 0.5 seconds.
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+    // There should be no new events generated.
+    auto events = mEventQueue.flush();
+    EXPECT_EQ((size_t)0, events.size());
+}
+
+TEST_F(DefaultVhalImplTest, testUnsubscribeInvalidProp) {
+    EXPECT_EQ(StatusCode::INVALID_ARG, mHal->unsubscribe(toInt(VehicleProperty::INFO_MAKE)));
+}
+
+int createMemfd(hidl_handle* fd) {
+    native_handle_t* handle = native_handle_create(/*numFds=*/1, /*numInts=*/0);
+    int memfd = memfd_create("memfile", 0);
+    handle->data[0] = dup(memfd);
+    fd->setTo(handle, /*shouldOwn=*/true);
+    return memfd;
+}
+
+TEST_F(DefaultVhalImplTest, testDump) {
+    hidl_vec<hidl_string> options;
+    hidl_handle fd = {};
+    int memfd = createMemfd(&fd);
+
+    ASSERT_TRUE(mHal->dump(fd, options));
+
+    lseek(memfd, 0, SEEK_SET);
+    char buf[10240] = {};
+    read(memfd, buf, sizeof(buf));
+    close(memfd);
+
+    // Read one property and check that it is in the dumped info.
+    VehiclePropValue value;
+    StatusCode status;
+    value.prop = toInt(VehicleProperty::INFO_MAKE);
+    auto gotValue = mHal->get(value, &status);
+    ASSERT_EQ(StatusCode::OK, status);
+    // Server side prop store does not have timestamp.
+    gotValue->timestamp = 0;
+
+    std::string infoMake = toString(*gotValue);
+    EXPECT_THAT(std::string(buf), HasSubstr(infoMake));
+}
+
+TEST_F(DefaultVhalImplTest, testSetPropInvalidAreaId) {
+    VehiclePropValue propNormal = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+                                   .areaId = HVAC_ALL,
+                                   .value.int32Values = {3}};
+    StatusCode status = mHal->set(propNormal);
+
+    EXPECT_EQ(StatusCode::OK, status);
+
+    // HVAC_FAN_SPEED only have HVAC_ALL area config and is not allowed to set by LEFT/RIGHT.
+    VehiclePropValue propWrongId = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+                                    .areaId = HVAC_LEFT,
+                                    .value.int32Values = {3}};
+
+    status = mHal->set(propWrongId);
+
+    EXPECT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+class DefaultVhalImplSetInvalidPropTest : public DefaultVhalImplTest,
+                                          public testing::WithParamInterface<VehiclePropValue> {};
+
+std::vector<VehiclePropValue> GenSetInvalidPropParams() {
+    std::vector<VehiclePropValue> props;
+    // int prop with no value.
+    VehiclePropValue intProp = {.prop = toInt(VehicleProperty::INFO_MODEL_YEAR)};
+    props.push_back(intProp);
+
+    // int prop with more than one value.
+    VehiclePropValue intPropWithValues = {.prop = toInt(VehicleProperty::INFO_MODEL_YEAR)};
+    intPropWithValues.value.int32Values.resize(2);
+    props.push_back(intPropWithValues);
+
+    // int vec prop with no value.
+    VehiclePropValue intVecProp = {.prop = toInt(VehicleProperty::INFO_FUEL_TYPE)};
+    props.push_back(intVecProp);
+
+    // int64 prop with no value.
+    VehiclePropValue int64Prop = {.prop = toInt(VehicleProperty::EPOCH_TIME)};
+    props.push_back(int64Prop);
+
+    // int64 prop with more than one value.
+    VehiclePropValue int64PropWithValues = {.prop = toInt(VehicleProperty::EPOCH_TIME)};
+    int64PropWithValues.value.int64Values.resize(2);
+    props.push_back(int64PropWithValues);
+
+    // int64 vec prop with no value.
+    VehiclePropValue int64VecProp = {.prop = toInt(VehicleProperty::WHEEL_TICK)};
+    props.push_back(int64VecProp);
+
+    // float prop with no value.
+    VehiclePropValue floatProp = {.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY)};
+    props.push_back(floatProp);
+
+    // float prop with more than one value.
+    VehiclePropValue floatPropWithValues = {.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY)};
+    floatPropWithValues.value.floatValues.resize(2);
+    props.push_back(floatPropWithValues);
+
+    // float vec prop with no value.
+    VehiclePropValue floatVecProp = {
+            .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION)};
+    props.push_back(floatVecProp);
+
+    // bool prop with no value.
+    VehiclePropValue boolProp = {
+            .prop = toInt(VehicleProperty::FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME)};
+    props.push_back(boolProp);
+
+    // bool prop with more than one value.
+    VehiclePropValue boolPropWithValues = {
+            .prop = toInt(VehicleProperty::FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME)};
+    boolPropWithValues.value.int32Values.resize(2);
+    props.push_back(boolPropWithValues);
+
+    // mixed prop.
+    // .configArray = {1, 1, 0, 2, 0, 0, 1, 0, 0}
+    // 1 string, 1 int, 0 bool, 2 ints, 0 int64, 0 int64s, 1 float, 0 floats, 0 bytes
+    VehiclePropValue mixedProp1 = {.prop = kMixedTypePropertyForTest};
+    // Expect 1 bool, and 2 ints, we only have 1 value.
+    mixedProp1.value.int32Values.resize(1);
+    mixedProp1.value.floatValues.resize(1);
+    props.push_back(mixedProp1);
+
+    VehiclePropValue mixedProp2 = {.prop = kMixedTypePropertyForTest};
+    mixedProp2.value.int32Values.resize(3);
+    // Missing float value.
+    mixedProp2.value.floatValues.resize(0);
+    props.push_back(mixedProp2);
+
+    return props;
+}
+
+TEST_P(DefaultVhalImplSetInvalidPropTest, testSetInvalidPropValue) {
+    VehiclePropValue value = GetParam();
+
+    StatusCode status = mHal->set(value);
+
+    EXPECT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+INSTANTIATE_TEST_SUITE_P(DefaultVhalImplSetInvalidPropTests, DefaultVhalImplSetInvalidPropTest,
+                         testing::ValuesIn(GenSetInvalidPropParams()));
+
+struct SetPropRangeTestCase {
+    std::string name;
+    VehiclePropValue prop;
+    StatusCode code;
+};
+
+class DefaultVhalImplSetPropRangeTest : public DefaultVhalImplTest,
+                                        public testing::WithParamInterface<SetPropRangeTestCase> {};
+
+std::vector<SetPropRangeTestCase> GenSetPropRangeParams() {
+    std::vector<SetPropRangeTestCase> tc;
+    VehiclePropValue intPropNormal = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+                                      .areaId = HVAC_ALL,
+                                      // min: 1, max: 7
+                                      .value.int32Values = {3}};
+    tc.push_back({"normal_case_int", intPropNormal, StatusCode::OK});
+
+    VehiclePropValue intPropSmall = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+                                     .areaId = HVAC_ALL,
+                                     // min: 1, max: 7
+                                     .value.int32Values = {0}};
+    tc.push_back({"normal_case_int_too_small", intPropSmall, StatusCode::INVALID_ARG});
+
+    VehiclePropValue intPropLarge = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+                                     .areaId = HVAC_ALL,
+                                     // min: 1, max: 7
+                                     .value.int32Values = {8}};
+    tc.push_back({"normal_case_int_too_large", intPropLarge, StatusCode::INVALID_ARG});
+
+    VehiclePropValue floatPropNormal = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
+                                        .areaId = HVAC_LEFT,
+                                        // min: 16, max: 32
+                                        .value.floatValues = {26}};
+    tc.push_back({"normal_case_float", floatPropNormal, StatusCode::OK});
+    VehiclePropValue floatPropSmall = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
+                                       .areaId = HVAC_LEFT,
+                                       // min: 16, max: 32
+                                       .value.floatValues = {15.5}};
+    tc.push_back({"normal_case_float_too_small", floatPropSmall, StatusCode::INVALID_ARG});
+    VehiclePropValue floatPropLarge = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
+                                       .areaId = HVAC_LEFT,
+                                       // min: 16, max: 32
+                                       .value.floatValues = {32.6}};
+    tc.push_back({"normal_case_float_too_large", floatPropLarge, StatusCode::INVALID_ARG});
+
+    return tc;
+}
+
+TEST_P(DefaultVhalImplSetPropRangeTest, testSetPropRange) {
+    SetPropRangeTestCase tc = GetParam();
+
+    StatusCode status = mHal->set(tc.prop);
+
+    EXPECT_EQ(tc.code, status);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        DefaultVhalImplSetPropRangeTests, DefaultVhalImplSetPropRangeTest,
+        testing::ValuesIn(GenSetPropRangeParams()),
+        [](const testing::TestParamInfo<DefaultVhalImplSetPropRangeTest::ParamType>& info) {
+            return info.param.name;
+        });
+
+std::string getPropIdString(VehicleProperty prop) {
+    char s[MAX_PROP_ID_LENGTH] = {};
+    snprintf(s, sizeof(s), "%d", toInt(prop));
+    return std::string(s);
+}
+
+struct OptionsTestCase {
+    std::string name;
+    hidl_vec<hidl_string> options;
+    std::string expectMsg;
+};
+
+class DefaultVhalImplOptionsTest : public DefaultVhalImplTest,
+                                   public testing::WithParamInterface<OptionsTestCase> {};
+
+TEST_P(DefaultVhalImplOptionsTest, testInvalidOptions) {
+    auto tc = GetParam();
+    hidl_handle fd = {};
+    int memfd = createMemfd(&fd);
+
+    bool shouldDump = mHal->dump(fd, tc.options);
+
+    EXPECT_FALSE(shouldDump);
+    char buf[10240] = {};
+    lseek(memfd, 0, SEEK_SET);
+    read(memfd, buf, sizeof(buf));
+    EXPECT_THAT(std::string(buf), HasSubstr(tc.expectMsg));
+}
+
+std::vector<OptionsTestCase> GenInvalidOptions() {
+    return {{"no_command", {"--debughal"}, "No command specified"},
+            {"unknown_command", {"--debughal", "--unknown"}, "Unknown command: \"--unknown\""},
+            {"help", {"--debughal", "--help"}, "Help:"},
+            {"genfakedata_no_subcommand",
+             {"--debughal", "--genfakedata"},
+             "No subcommand specified for genfakedata"},
+            {"genfakedata_unknown_subcommand",
+             {"--debughal", "--genfakedata", "--unknown"},
+             "Unknown command: \"--unknown\""},
+            {"genfakedata_start_linear_no_args",
+             {"--debughal", "--genfakedata", "--startlinear"},
+             "incorrect argument count"},
+            {"genfakedata_start_linear_invalid_propId",
+             {"--debughal", "--genfakedata", "--startlinear", "abcd", "0.1", "0.1", "0.1", "0.1",
+              "100000000"},
+             "failed to parse propdID as int: \"abcd\""},
+            {"genfakedata_start_linear_invalid_middleValue",
+             {"--debughal", "--genfakedata", "--startlinear", "1", "abcd", "0.1", "0.1", "0.1",
+              "100000000"},
+             "failed to parse middleValue as float: \"abcd\""},
+            {"genfakedata_start_linear_invalid_currentValue",
+             {"--debughal", "--genfakedata", "--startlinear", "1", "0.1", "abcd", "0.1", "0.1",
+              "100000000"},
+             "failed to parse currentValue as float: \"abcd\""},
+            {"genfakedata_start_linear_invalid_dispersion",
+             {"--debughal", "--genfakedata", "--startlinear", "1", "0.1", "0.1", "abcd", "0.1",
+              "100000000"},
+             "failed to parse dispersion as float: \"abcd\""},
+            {"genfakedata_start_linear_invalid_increment",
+             {"--debughal", "--genfakedata", "--startlinear", "1", "0.1", "0.1", "0.1", "abcd",
+              "100000000"},
+             "failed to parse increment as float: \"abcd\""},
+            {"genfakedata_start_linear_invalid_interval",
+             {"--debughal", "--genfakedata", "--startlinear", "1", "0.1", "0.1", "0.1", "0.1",
+              "0.1"},
+             "failed to parse interval as int: \"0.1\""},
+            {"genfakedata_stop_linear_no_args",
+             {"--debughal", "--genfakedata", "--stoplinear"},
+             "incorrect argument count"},
+            {"genfakedata_stop_linear_invalid_propId",
+             {"--debughal", "--genfakedata", "--stoplinear", "abcd"},
+             "failed to parse propdID as int: \"abcd\""},
+            {"genfakedata_startjson_no_args",
+             {"--debughal", "--genfakedata", "--startjson"},
+             "incorrect argument count"},
+            {"genfakedata_startjson_invalid_repetition",
+             {"--debughal", "--genfakedata", "--startjson", "file", "0.1"},
+             "failed to parse repetition as int: \"0.1\""},
+            {"genfakedata_startjson_invalid_json_file",
+             {"--debughal", "--genfakedata", "--startjson", "file", "1"},
+             "invalid JSON file"},
+            {"genfakedata_stopjson_no_args",
+             {"--debughal", "--genfakedata", "--stopjson"},
+             "incorrect argument count"},
+            {"genfakedata_keypress_no_args",
+             {"--debughal", "--genfakedata", "--keypress"},
+             "incorrect argument count"},
+            {"genfakedata_keypress_invalid_keyCode",
+             {"--debughal", "--genfakedata", "--keypress", "0.1", "1"},
+             "failed to parse keyCode as int: \"0.1\""},
+            {"genfakedata_keypress_invalid_display",
+             {"--debughal", "--genfakedata", "--keypress", "1", "0.1"},
+             "failed to parse display as int: \"0.1\""},
+            {"setint_no_args", {"--debughal", "--setint"}, "incorrect argument count"},
+            {"setint_invalid_prop_id",
+             {"--debughal", "--setint", "abcd", "0", "0", "0"},
+             "failed to parse propID as int: \"abcd\""},
+            {"setint_invalid_value",
+             {"--debughal", "--setint", "0", "1.1", "0", "0"},
+             "failed to parse value as int: \"1.1\""},
+            {"setint_invalid_timestamp",
+             {"--debughal", "--setint", "0", "0", "1.1", "0"},
+             "failed to parse timestamp as int: \"1.1\""},
+            {"setint_invalid_areaId",
+             {"--debughal", "--setint", "0", "0", "0", "1.1"},
+             "failed to parse areaID as int: \"1.1\""},
+            {"setbool_no_args", {"--debughal", "--setbool"}, "incorrect argument count"},
+            {"setbool_invalid_value",
+             {"--debughal", "--setbool", "0", "1", "0", "0"},
+             "failed to parse value as bool"},
+            {"setfloat_no_args", {"--debughal", "--setfloat"}, "incorrect argument count"},
+            {"setfloat_invalid_value",
+             {"--debughal", "--setfloat", "0", "abcd", "0", "0"},
+             "failed to parse value as float: \"abcd\""}};
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        DefaultVhalImplOptionsTests, DefaultVhalImplOptionsTest,
+        testing::ValuesIn(GenInvalidOptions()),
+        [](const testing::TestParamInfo<DefaultVhalImplOptionsTest::ParamType>& info) {
+            return info.param.name;
+        });
+
+TEST_F(DefaultVhalImplTest, testDebugGenFakeDataLinear) {
+    // Start a fake linear data generator for vehicle speed at 0.1s interval.
+    // range: 0 - 100, current value: 30, step: 20.
+    hidl_vec<hidl_string> options = {"--debughal",
+                                     "--genfakedata",
+                                     "--startlinear",
+                                     getPropIdString(VehicleProperty::PERF_VEHICLE_SPEED),
+                                     /*middleValue=*/"50",
+                                     /*currentValue=*/"30",
+                                     /*dispersion=*/"50",
+                                     /*increment=*/"20",
+                                     /*interval=*/"100000000"};
+    hidl_handle fd = {};
+    int memfd = createMemfd(&fd);
+    // Clear existing events.
+    mEventQueue.flush();
+
+    EXPECT_FALSE(mHal->dump(fd, options));
+
+    lseek(memfd, 0, SEEK_SET);
+    char buf[10240] = {};
+    // The dumped info should be empty.
+    read(memfd, buf, sizeof(buf));
+    EXPECT_STREQ("", buf);
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+
+    auto events = mEventQueue.flush();
+    // We should get 10 events ideally, but let's be safe here.
+    ASSERT_LE((size_t)5, events.size());
+    int32_t value = 30;
+    for (size_t i = 0; i < 5; i++) {
+        ASSERT_EQ((size_t)1, events[i]->value.floatValues.size());
+        EXPECT_EQ((float)value, events[i]->value.floatValues[0]);
+        value = (value + 20) % 100;
+    }
+
+    // Stop the linear generator.
+    options = {"--debughal", "--genfakedata", "--stoplinear",
+               getPropIdString(VehicleProperty::PERF_VEHICLE_SPEED)};
+    EXPECT_FALSE(mHal->dump(fd, options));
+
+    // The dumped info should be empty.
+    lseek(memfd, 0, SEEK_SET);
+    read(memfd, buf, sizeof(buf));
+    EXPECT_STREQ("", buf);
+
+    close(memfd);
+
+    // Clear existing events.
+    mEventQueue.flush();
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+    // There should be no new events generated.
+    EXPECT_EQ((size_t)0, mEventQueue.flush().size());
+}
+
+std::string getTestFilePath(const char* filename) {
+    static std::string baseDir = android::base::GetExecutableDirectory();
+    return baseDir + "/" + filename;
+}
+
+TEST_F(DefaultVhalImplTest, testDebugGenFakeDataJson) {
+    hidl_vec<hidl_string> options = {"--debughal", "--genfakedata", "--startjson",
+                                     getTestFilePath("prop.json"), "2"};
+    hidl_handle fd = {};
+    int memfd = createMemfd(&fd);
+    // Clear existing events.
+    mEventQueue.flush();
+
+    EXPECT_FALSE(mHal->dump(fd, options));
+
+    lseek(memfd, 0, SEEK_SET);
+    char buf[10240] = {};
+    // The dumped info should be empty.
+    read(memfd, buf, sizeof(buf));
+    EXPECT_STREQ("", buf);
+
+    // wait for some time.
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    auto events = mEventQueue.flush();
+    ASSERT_EQ((size_t)8, events.size());
+    // First set of events, we test 1st and the last.
+    EXPECT_EQ((size_t)1, events[0]->value.int32Values.size());
+    EXPECT_EQ(8, events[0]->value.int32Values[0]);
+    EXPECT_EQ((size_t)1, events[3]->value.int32Values.size());
+    EXPECT_EQ(10, events[3]->value.int32Values[0]);
+    // Second set of the same events.
+    EXPECT_EQ((size_t)1, events[4]->value.int32Values.size());
+    EXPECT_EQ(8, events[4]->value.int32Values[0]);
+    EXPECT_EQ((size_t)1, events[7]->value.int32Values.size());
+    EXPECT_EQ(10, events[7]->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testDebugGenFakeDataKeyPress) {
+    hidl_vec<hidl_string> options = {"--debughal", "--genfakedata", "--keypress", "1", "2"};
+    hidl_handle fd = {};
+    int memfd = createMemfd(&fd);
+    // Clear existing events.
+    mEventQueue.flush();
+
+    EXPECT_FALSE(mHal->dump(fd, options));
+
+    lseek(memfd, 0, SEEK_SET);
+    char buf[10240] = {};
+    // The dumped info should be empty.
+    read(memfd, buf, sizeof(buf));
+    EXPECT_STREQ("", buf);
+
+    auto events = mEventQueue.flush();
+    ASSERT_EQ((size_t)2, events.size());
+    EXPECT_EQ(toInt(VehicleProperty::HW_KEY_INPUT), events[0]->prop);
+    EXPECT_EQ(toInt(VehicleProperty::HW_KEY_INPUT), events[1]->prop);
+    ASSERT_EQ((size_t)3, events[0]->value.int32Values.size());
+    ASSERT_EQ((size_t)3, events[1]->value.int32Values.size());
+    EXPECT_EQ(toInt(VehicleHwKeyInputAction::ACTION_DOWN), events[0]->value.int32Values[0]);
+    EXPECT_EQ(1, events[0]->value.int32Values[1]);
+    EXPECT_EQ(2, events[0]->value.int32Values[2]);
+    EXPECT_EQ(toInt(VehicleHwKeyInputAction::ACTION_UP), events[1]->value.int32Values[0]);
+    EXPECT_EQ(1, events[1]->value.int32Values[1]);
+    EXPECT_EQ(2, events[1]->value.int32Values[2]);
+}
+
+TEST_F(DefaultVhalImplTest, testHeartBeatEvent) {
+    // A heart beat would be sent every 3s, but let's wait for 6s to be sure at least 2 events have
+    // been generated (at 0s and 3s).
+    std::this_thread::sleep_for(std::chrono::milliseconds(6000));
+
+    auto events = mHeartBeatQueue.flush();
+    ASSERT_GE(events.size(), (size_t)2);
+    ASSERT_EQ(toInt(VehicleProperty::VHAL_HEARTBEAT), events[0]->prop);
+}
+
+TEST_F(DefaultVhalImplTest, testVendorOverrideProperties) {
+    // Destroy the existing VHAL first to prevent it using destroyed connector or propstore.
+    mHal.reset();
+    // Create a new Default VHAL and reinitialize it to load the override properties.
+    std::string overrideDir = android::base::GetExecutableDirectory() + "/override/";
+    mPropStore.reset(new VehiclePropertyStore);
+    mConnector.reset(new DefaultVehicleConnector);
+    mConnector->setValuePool(&mValueObjectPool);
+    mHal.reset(new DefaultVehicleHal(mPropStore.get(), mConnector.get()));
+    // Set vendor override directory.
+    DefaultVhalImplTestHelper helper(mConnector.get());
+    helper.overrideProperties(overrideDir.c_str());
+
+    initHal();
+
+    VehiclePropValue value;
+    StatusCode status;
+    // This is the same as the prop in 'gear_selection.json'.
+    value.prop = toInt(VehicleProperty::GEAR_SELECTION);
+
+    auto gotValue = mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.int32Values.size());
+    ASSERT_EQ(8, gotValue->value.int32Values[0]);
+
+    // If we set the value, it should update despite the override.
+    value.prop = toInt(VehicleProperty::GEAR_SELECTION);
+    value.value.int32Values.resize(1);
+    value.value.int32Values[0] = 5;
+
+    status = mHal->set(value);
+    ASSERT_EQ(StatusCode::OK, status);
+
+    gotValue = mHal->get(value, &status);
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.int32Values.size());
+    ASSERT_EQ(5, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testVendorOverridePropertiesMultipleAreas) {
+    // Destroy the existing VHAL first to prevent it using destroyed connector or propstore.
+    mHal.reset();
+    // Create a new Default VHAL and reinitialize it to load the override properties.
+    std::string overrideDir = android::base::GetExecutableDirectory() + "/override/";
+    mPropStore.reset(new VehiclePropertyStore);
+    mConnector.reset(new DefaultVehicleConnector);
+    mConnector->setValuePool(&mValueObjectPool);
+    mHal.reset(new DefaultVehicleHal(mPropStore.get(), mConnector.get()));
+    // Set vendor override directory.
+    DefaultVhalImplTestHelper helper(mConnector.get());
+    helper.overrideProperties(overrideDir.c_str());
+
+    initHal();
+
+    VehiclePropValue value;
+    StatusCode status;
+    // This is the same as the prop in 'hvac_temperature_set.json'.
+    value.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET);
+    value.areaId = HVAC_LEFT;
+
+    auto gotValue = mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.floatValues.size());
+    ASSERT_EQ(30.0f, gotValue->value.floatValues[0]);
+
+    // HVAC_RIGHT should not be affected and return the default value.
+    value.areaId = HVAC_RIGHT;
+
+    gotValue = mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.floatValues.size());
+    ASSERT_EQ(20.0f, gotValue->value.floatValues[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testVendorOverridePropertiesDirDoesNotExist) {
+    // Destroy the existing VHAL first to prevent it using destroyed connector or propstore.
+    mHal.reset();
+    // Create a new Default VHAL and reinitialize it to load the override properties.
+    mPropStore.reset(new VehiclePropertyStore);
+    mConnector.reset(new DefaultVehicleConnector);
+    mConnector->setValuePool(&mValueObjectPool);
+    mHal.reset(new DefaultVehicleHal(mPropStore.get(), mConnector.get()));
+    // Set vendor override directory to a non-existing dir
+    DefaultVhalImplTestHelper helper(mConnector.get());
+    helper.overrideProperties("123");
+    initHal();
+
+    VehiclePropValue value;
+    StatusCode status;
+    value.prop = toInt(VehicleProperty::GEAR_SELECTION);
+
+    auto gotValue = mHal->get(value, &status);
+
+    // We should get the default value.
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.int32Values.size());
+    ASSERT_EQ(4, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testGetObd2FreezeFrameNoTimestamp) {
+    VehiclePropValue value;
+    value.prop = OBD2_FREEZE_FRAME;
+    StatusCode status;
+
+    auto gotValue = mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+TEST_F(DefaultVhalImplTest, testGetObd2FreezeFrameInvalidTimestamp) {
+    VehiclePropValue value;
+    value.prop = OBD2_FREEZE_FRAME;
+    value.value.int64Values.resize(1);
+    value.value.int64Values[0] = 0;
+    StatusCode status;
+
+    auto gotValue = mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+TEST_F(DefaultVhalImplTest, testGetObd2FreezeFrameInfoGetObd2FreezeFrame) {
+    VehiclePropValue value;
+    value.prop = OBD2_FREEZE_FRAME_INFO;
+    StatusCode status;
+
+    auto gotValue = mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)3, gotValue->value.int64Values.size());
+
+    std::vector<std::string> dtcs;
+    std::vector<std::string> sampleDtcs = {"P0070", "P0102", "P0123"};
+    for (int64_t timestamp : gotValue->value.int64Values) {
+        VehiclePropValue freezeFrameRequest;
+        freezeFrameRequest.prop = OBD2_FREEZE_FRAME;
+        freezeFrameRequest.value.int64Values.resize(1);
+        freezeFrameRequest.value.int64Values[0] = timestamp;
+
+        auto freezeFrameValue = mHal->get(freezeFrameRequest, &status);
+
+        ASSERT_EQ(StatusCode::OK, status);
+        // Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + 1
+        EXPECT_EQ((size_t)32, freezeFrameValue->value.int32Values.size());
+        // Obd2FloatSensorIndex.LAST_SYSTEM_INDEX + 1
+        EXPECT_EQ((size_t)71, freezeFrameValue->value.floatValues.size());
+        // (intValues.size() + floatValues.size()) / 8
+        EXPECT_EQ((size_t)13, freezeFrameValue->value.bytes.size());
+
+        dtcs.push_back(freezeFrameValue->value.stringValue);
+    }
+
+    for (std::string expectDtc : sampleDtcs) {
+        EXPECT_NE(std::find(dtcs.begin(), dtcs.end(), expectDtc), dtcs.end());
+    }
+}
+
+TEST_F(DefaultVhalImplTest, testGetObd2LiveFrame) {
+    VehiclePropValue value;
+    value.prop = OBD2_LIVE_FRAME;
+    StatusCode status;
+
+    auto gotValue = mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::OK, status);
+    // Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + 1
+    EXPECT_EQ((size_t)32, gotValue->value.int32Values.size());
+    // Obd2FloatSensorIndex.LAST_SYSTEM_INDEX + 1
+    EXPECT_EQ((size_t)71, gotValue->value.floatValues.size());
+    // (intValues.size() + floatValues.size()) / 8
+    EXPECT_EQ((size_t)13, gotValue->value.bytes.size());
+}
+
+TEST_F(DefaultVhalImplTest, testClearObd2FreezeFrameAll) {
+    VehiclePropValue value;
+    value.prop = OBD2_FREEZE_FRAME_CLEAR;
+    // No int64Values is to clear all frames.
+
+    auto status = mHal->set(value);
+
+    EXPECT_EQ(StatusCode::OK, status);
+
+    VehiclePropValue freezeFrameRequest;
+    freezeFrameRequest.prop = OBD2_FREEZE_FRAME;
+    freezeFrameRequest.value.int64Values.resize(1);
+
+    auto gotValue = mHal->get(freezeFrameRequest, &status);
+
+    EXPECT_EQ(StatusCode::NOT_AVAILABLE, status);
+
+    VehiclePropValue freezeFrameInfoRequest;
+    freezeFrameInfoRequest.prop = OBD2_FREEZE_FRAME_INFO;
+
+    gotValue = mHal->get(freezeFrameInfoRequest, &status);
+
+    EXPECT_EQ(StatusCode::OK, status);
+    EXPECT_EQ((size_t)0, gotValue->value.int64Values.size());
+}
+
+TEST_F(DefaultVhalImplTest, testClearObd2FreezeFrameOneFrame) {
+    // Get existing freeze frame info first.
+    VehiclePropValue frameInfoRequest;
+    frameInfoRequest.prop = OBD2_FREEZE_FRAME_INFO;
+    StatusCode status;
+    auto gotValue = mHal->get(frameInfoRequest, &status);
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)3, gotValue->value.int64Values.size());
+
+    VehiclePropValue clearRequest;
+    int64_t timestamp = gotValue->value.int64Values[0];
+    clearRequest.prop = OBD2_FREEZE_FRAME_CLEAR;
+    clearRequest.value.int64Values.resize(1);
+    clearRequest.value.int64Values[0] = timestamp;
+
+    // Try to clear the first frame.
+    status = mHal->set(clearRequest);
+
+    // Get freeze frame info again.
+    gotValue = mHal->get(frameInfoRequest, &status);
+
+    ASSERT_EQ(StatusCode::OK, status);
+    // Now we should only have 2 frames.
+    ASSERT_EQ((size_t)2, gotValue->value.int64Values.size());
+
+    // Try to get the deleted frame, should fail.
+    VehiclePropValue frameRequest;
+    frameRequest.prop = OBD2_FREEZE_FRAME;
+    frameRequest.value.int64Values.resize(1);
+    frameRequest.value.int64Values[0] = timestamp;
+
+    gotValue = mHal->get(frameRequest, &status);
+
+    ASSERT_EQ(StatusCode::INVALID_ARG, status);
+
+    // Clear the same frame again should fail.
+    status = mHal->set(clearRequest);
+
+    ASSERT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+TEST_F(DefaultVhalImplTest, testGetUserPropertySetOnly) {
+    VehiclePropValue value;
+    value.prop = toInt(VehicleProperty::INITIAL_USER_INFO);
+    StatusCode status;
+
+    mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::INVALID_ARG, status);
+
+    value.prop = toInt(VehicleProperty::SWITCH_USER);
+
+    mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::INVALID_ARG, status);
+
+    value.prop = toInt(VehicleProperty::CREATE_USER);
+
+    mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::INVALID_ARG, status);
+
+    value.prop = toInt(VehicleProperty::REMOVE_USER);
+
+    mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+TEST_F(DefaultVhalImplTest, testGetUserIdAssoc) {
+    VehiclePropValue value;
+    value.prop = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+    StatusCode status;
+
+    mHal->get(value, &status);
+
+    // Default returns NOT_AVAILABLE.
+    ASSERT_EQ(StatusCode::NOT_AVAILABLE, status);
+
+    // This is the same example as used in User HAL Emulation doc.
+    VehiclePropValue setValue = {
+            .prop = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION),
+            .areaId = 1,
+            .value.int32Values = {666, 1, 1, 2},
+    };
+
+    status = mHal->set(setValue);
+
+    ASSERT_EQ(StatusCode::OK, status);
+
+    auto gotValue = mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)4, gotValue->value.int32Values.size());
+    EXPECT_EQ(1, gotValue->areaId);
+    EXPECT_EQ(666, gotValue->value.int32Values[0]);
+    EXPECT_EQ(1, gotValue->value.int32Values[1]);
+    EXPECT_EQ(1, gotValue->value.int32Values[2]);
+    EXPECT_EQ(2, gotValue->value.int32Values[3]);
+    EXPECT_EQ(toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION), gotValue->prop);
+}
+
+TEST_F(DefaultVhalImplTest, testSwitchUser) {
+    // This is the same example as used in User HAL Emulation doc.
+    VehiclePropValue setValue = {
+            .prop = toInt(VehicleProperty::SWITCH_USER),
+            .areaId = 1,
+            .value.int32Values = {666, 3, 2},
+    };
+
+    auto status = mHal->set(setValue);
+
+    ASSERT_EQ(StatusCode::OK, status);
+
+    // Simulate a request from Android side.
+    setValue = {
+            .prop = toInt(VehicleProperty::SWITCH_USER),
+            .areaId = 0,
+            .value.int32Values = {666, 3},
+    };
+    // Clear existing events.
+    mEventQueue.flush();
+
+    status = mHal->set(setValue);
+
+    ASSERT_EQ(StatusCode::OK, status);
+
+    // Should generate an event for user hal response.
+    auto events = mEventQueue.flush();
+    ASSERT_EQ((size_t)1, events.size());
+    EXPECT_EQ(1, events[0]->areaId);
+    EXPECT_EQ(toInt(VehicleProperty::SWITCH_USER), events[0]->prop);
+    ASSERT_EQ((size_t)3, events[0]->value.int32Values.size());
+    EXPECT_EQ(666, events[0]->value.int32Values[0]);
+    EXPECT_EQ(3, events[0]->value.int32Values[1]);
+    EXPECT_EQ(2, events[0]->value.int32Values[2]);
+
+    // Try to get switch_user again, should return default value.
+    status = mHal->set(setValue);
+    ASSERT_EQ(StatusCode::OK, status);
+
+    events = mEventQueue.flush();
+    ASSERT_EQ((size_t)1, events.size());
+    EXPECT_EQ(0, events[0]->areaId);
+    EXPECT_EQ(toInt(VehicleProperty::SWITCH_USER), events[0]->prop);
+    ASSERT_EQ((size_t)3, events[0]->value.int32Values.size());
+    // Request ID
+    EXPECT_EQ(666, events[0]->value.int32Values[0]);
+    // VEHICLE_RESPONSE
+    EXPECT_EQ(3, events[0]->value.int32Values[1]);
+    // SUCCESS
+    EXPECT_EQ(1, events[0]->value.int32Values[2]);
+}
+
+TEST_F(DefaultVhalImplTest, testCreateUser) {
+    // This is the same example as used in User HAL Emulation doc.
+    VehiclePropValue setValue = {
+            .prop = toInt(VehicleProperty::CREATE_USER),
+            .areaId = 1,
+            .value.int32Values = {666, 2},
+    };
+
+    auto status = mHal->set(setValue);
+
+    ASSERT_EQ(StatusCode::OK, status);
+
+    // Simulate a request from Android side.
+    setValue = {
+            .prop = toInt(VehicleProperty::CREATE_USER),
+            .areaId = 0,
+            .value.int32Values = {666},
+    };
+    // Clear existing events.
+    mEventQueue.flush();
+
+    status = mHal->set(setValue);
+
+    ASSERT_EQ(StatusCode::OK, status);
+
+    // Should generate an event for user hal response.
+    auto events = mEventQueue.flush();
+    ASSERT_EQ((size_t)1, events.size());
+    EXPECT_EQ(1, events[0]->areaId);
+    EXPECT_EQ(toInt(VehicleProperty::CREATE_USER), events[0]->prop);
+    ASSERT_EQ((size_t)2, events[0]->value.int32Values.size());
+    EXPECT_EQ(666, events[0]->value.int32Values[0]);
+    EXPECT_EQ(2, events[0]->value.int32Values[1]);
+
+    // Try to get create_user again, should return default value.
+    status = mHal->set(setValue);
+    ASSERT_EQ(StatusCode::OK, status);
+
+    events = mEventQueue.flush();
+    ASSERT_EQ((size_t)1, events.size());
+    EXPECT_EQ(0, events[0]->areaId);
+    EXPECT_EQ(toInt(VehicleProperty::CREATE_USER), events[0]->prop);
+    ASSERT_EQ((size_t)2, events[0]->value.int32Values.size());
+    // Request ID
+    EXPECT_EQ(666, events[0]->value.int32Values[0]);
+    // SUCCESS
+    EXPECT_EQ(1, events[0]->value.int32Values[1]);
+}
+
+TEST_F(DefaultVhalImplTest, testInitialUserInfo) {
+    // This is the same example as used in User HAL Emulation doc.
+    VehiclePropValue setValue = {
+            .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
+            .areaId = 1,
+            .value.int32Values = {666, 1, 11},
+    };
+
+    auto status = mHal->set(setValue);
+
+    ASSERT_EQ(StatusCode::OK, status);
+
+    // Simulate a request from Android side.
+    setValue = {
+            .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
+            .areaId = 0,
+            .value.int32Values = {3},
+    };
+    // Clear existing events.
+    mEventQueue.flush();
+
+    status = mHal->set(setValue);
+
+    ASSERT_EQ(StatusCode::OK, status);
+
+    // Should generate an event for user hal response.
+    auto events = mEventQueue.flush();
+    ASSERT_EQ((size_t)1, events.size());
+    EXPECT_EQ(1, events[0]->areaId);
+    EXPECT_EQ(toInt(VehicleProperty::INITIAL_USER_INFO), events[0]->prop);
+    ASSERT_EQ((size_t)3, events[0]->value.int32Values.size());
+    EXPECT_EQ(3, events[0]->value.int32Values[0]);
+    EXPECT_EQ(1, events[0]->value.int32Values[1]);
+    EXPECT_EQ(11, events[0]->value.int32Values[2]);
+
+    // Try to get create_user again, should return default value.
+    status = mHal->set(setValue);
+    ASSERT_EQ(StatusCode::OK, status);
+
+    events = mEventQueue.flush();
+    ASSERT_EQ((size_t)1, events.size());
+    EXPECT_EQ(0, events[0]->areaId);
+    EXPECT_EQ(toInt(VehicleProperty::INITIAL_USER_INFO), events[0]->prop);
+    ASSERT_EQ((size_t)4, events[0]->value.int32Values.size());
+    // Request ID
+    EXPECT_EQ(3, events[0]->value.int32Values[0]);
+    // ACTION: DEFAULT
+    EXPECT_EQ(0, events[0]->value.int32Values[1]);
+    // User id: 0
+    EXPECT_EQ(0, events[0]->value.int32Values[2]);
+    // Flags: 0
+    EXPECT_EQ(0, events[0]->value.int32Values[3]);
+}
+
+TEST_F(DefaultVhalImplTest, testDebugSetInt) {
+    hidl_vec<hidl_string> options = {"--debughal", "--setint",
+                                     getPropIdString(VehicleProperty::INFO_MODEL_YEAR), "2022",
+                                     "1000"};
+    hidl_handle fd = {};
+    int memfd = createMemfd(&fd);
+    // Clear existing events.
+    mEventQueue.flush();
+
+    EXPECT_FALSE(mHal->dump(fd, options));
+
+    lseek(memfd, 0, SEEK_SET);
+    char buf[10240] = {};
+    // The dumped info should be empty.
+    read(memfd, buf, sizeof(buf));
+    EXPECT_STREQ("", buf);
+
+    auto events = mEventQueue.flush();
+    ASSERT_EQ((size_t)1, events.size());
+    ASSERT_EQ((size_t)1, events[0]->value.int32Values.size());
+    EXPECT_EQ(2022, events[0]->value.int32Values[0]);
+    EXPECT_EQ(1000, events[0]->timestamp);
+
+    VehiclePropValue value;
+    StatusCode status;
+    value.prop = toInt(VehicleProperty::INFO_MODEL_YEAR);
+    auto gotValue = mHal->get(value, &status);
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.int32Values.size());
+    EXPECT_EQ(2022, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testDebugSetBool) {
+    char doorLeft[100];
+    snprintf(doorLeft, sizeof(doorLeft), "%d", DOOR_1_LEFT);
+    hidl_vec<hidl_string> options = {
+            "--debughal", "--setbool", getPropIdString(VehicleProperty::DOOR_LOCK),
+            "false",      "1000",      doorLeft};
+    hidl_handle fd = {};
+    int memfd = createMemfd(&fd);
+    // Clear existing events.
+    mEventQueue.flush();
+
+    EXPECT_FALSE(mHal->dump(fd, options));
+
+    lseek(memfd, 0, SEEK_SET);
+    char buf[10240] = {};
+    // The dumped info should be empty.
+    read(memfd, buf, sizeof(buf));
+    EXPECT_STREQ("", buf);
+
+    auto events = mEventQueue.flush();
+    ASSERT_EQ((size_t)1, events.size());
+    EXPECT_EQ(0, events[0]->value.int32Values[0]);
+    EXPECT_EQ(DOOR_1_LEFT, events[0]->areaId);
+    EXPECT_EQ(1000, events[0]->timestamp);
+
+    VehiclePropValue value;
+    StatusCode status;
+    value.prop = toInt(VehicleProperty::DOOR_LOCK);
+    value.areaId = DOOR_1_LEFT;
+    auto gotValue = mHal->get(value, &status);
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.int32Values.size());
+    EXPECT_EQ(0, gotValue->value.int32Values[0]);
+
+    value.areaId = DOOR_1_RIGHT;
+    gotValue = mHal->get(value, &status);
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.int32Values.size());
+    EXPECT_EQ(1, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testDebugSetFloat) {
+    hidl_vec<hidl_string> options = {"--debughal", "--setfloat",
+                                     getPropIdString(VehicleProperty::INFO_FUEL_CAPACITY), "10.5",
+                                     "1000"};
+    hidl_handle fd = {};
+    int memfd = createMemfd(&fd);
+    // Clear existing events.
+    mEventQueue.flush();
+
+    EXPECT_FALSE(mHal->dump(fd, options));
+
+    lseek(memfd, 0, SEEK_SET);
+    char buf[10240] = {};
+    // The dumped info should be empty.
+    read(memfd, buf, sizeof(buf));
+    EXPECT_STREQ("", buf);
+
+    auto events = mEventQueue.flush();
+    ASSERT_EQ((size_t)1, events.size());
+    ASSERT_EQ((size_t)1, events[0]->value.floatValues.size());
+    EXPECT_EQ(10.5, events[0]->value.floatValues[0]);
+    EXPECT_EQ(1000, events[0]->timestamp);
+
+    VehiclePropValue value;
+    StatusCode status;
+    value.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
+    auto gotValue = mHal->get(value, &status);
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.floatValues.size());
+    EXPECT_EQ(10.5, gotValue->value.floatValues[0]);
+}
+
+}  // namespace
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp
index 3817e44..a507b50 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp
@@ -17,9 +17,9 @@
 #include <gtest/gtest.h>
 
 #include <utils/SystemClock.h>
+#include <vhal_v2_0/ProtoMessageConverter.h>
 
 #include "vhal_v2_0/DefaultConfig.h"
-#include "vhal_v2_0/ProtoMessageConverter.h"
 #include "vhal_v2_0/VehicleUtils.h"
 
 namespace android {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/gear_selection.json b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/gear_selection.json
new file mode 100644
index 0000000..59666b8
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/gear_selection.json
@@ -0,0 +1,9 @@
+[
+  {
+    "timestamp": 1000000,
+    "areaId": 0,
+    "value": 8,
+    // GEAR_SELECTION
+    "prop": 289408000
+  }
+]
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/hvac_temperature_set.json b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/hvac_temperature_set.json
new file mode 100644
index 0000000..93a97ed
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/hvac_temperature_set.json
@@ -0,0 +1,10 @@
+[
+  {
+    "timestamp": 1000000,
+    // HVAC_LEFT
+    "areaId": 49,
+    "value": 30,
+    // HVAC_TEMPERATURE_SET
+    "prop": 358614275
+  }
+]
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/prop.json b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/prop.json
new file mode 100644
index 0000000..b881109
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/prop.json
@@ -0,0 +1,26 @@
+[
+  {
+    "timestamp": 1000000,
+    "areaId": 0,
+    "value": 8,
+    "prop": 289408000
+  },
+  {
+    "timestamp": 2000000,
+    "areaId": 0,
+    "value": 4,
+    "prop": 289408000
+  },
+  {
+    "timestamp": 3000000,
+    "areaId": 0,
+    "value": 16,
+    "prop": 289408000
+  },
+  {
+    "timestamp": 4000000,
+    "areaId": 0,
+    "value": 10,
+    "prop": 289408000
+  }
+]
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/Android.bp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/Android.bp
new file mode 100644
index 0000000..ad12527
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/Android.bp
@@ -0,0 +1,40 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Library used to emulate User HAL behavior through lshal debug requests.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library {
+    name: "android.hardware.automotive.vehicle@2.0-fake-user-hal-lib",
+    vendor: true,
+    defaults: ["vhal_v2_0_target_defaults"],
+    srcs: ["FakeUserHal.cpp"],
+    shared_libs: [
+        "libbase",
+        "libutils",
+        "libcutils",
+    ],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    whole_static_libs: [
+        "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
+    ],
+}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/FakeUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/FakeUserHal.cpp
new file mode 100644
index 0000000..e9ebcc6
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/FakeUserHal.cpp
@@ -0,0 +1,353 @@
+/*
+ * 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 "FakeUserHal"
+
+#include <cutils/log.h>
+#include <utils/SystemClock.h>
+
+#include "UserHalHelper.h"
+
+#include "FakeUserHal.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+namespace {
+
+using android::base::Error;
+using android::base::Result;
+
+constexpr int32_t INITIAL_USER_INFO = static_cast<int32_t>(VehicleProperty::INITIAL_USER_INFO);
+constexpr int32_t SWITCH_USER = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
+constexpr int32_t CREATE_USER = static_cast<int32_t>(VehicleProperty::CREATE_USER);
+constexpr int32_t REMOVE_USER = static_cast<int32_t>(VehicleProperty::REMOVE_USER);
+constexpr int32_t USER_IDENTIFICATION_ASSOCIATION =
+        static_cast<int32_t>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+
+Result<int32_t> getRequestId(const VehiclePropValue& value) {
+    if (value.value.int32Values.size() < 1) {
+        return Error(static_cast<int>(StatusCode::INVALID_ARG))
+               << "no int32values on " << toString(value);
+    }
+    return value.value.int32Values[0];
+}
+
+Result<SwitchUserMessageType> getSwitchUserMessageType(const VehiclePropValue& value) {
+    if (value.value.int32Values.size() < 2) {
+        return Error(static_cast<int>(StatusCode::INVALID_ARG))
+               << "missing switch user message type " << toString(value);
+    }
+    return user_hal_helper::verifyAndCast<SwitchUserMessageType>(value.value.int32Values[1]);
+}
+
+}  // namespace
+
+bool FakeUserHal::isSupported(int32_t prop) {
+    switch (prop) {
+        case INITIAL_USER_INFO:
+        case SWITCH_USER:
+        case CREATE_USER:
+        case REMOVE_USER:
+        case USER_IDENTIFICATION_ASSOCIATION:
+            return true;
+        default:
+            return false;
+    }
+}
+
+Result<std::unique_ptr<VehiclePropValue>> FakeUserHal::onSetProperty(
+        const VehiclePropValue& value) {
+    ALOGV("onSetProperty(): %s", toString(value).c_str());
+
+    switch (value.prop) {
+        case INITIAL_USER_INFO:
+            return onSetInitialUserInfoResponse(value);
+        case SWITCH_USER:
+            return onSetSwitchUserResponse(value);
+        case CREATE_USER:
+            return onSetCreateUserResponse(value);
+        case REMOVE_USER:
+            ALOGI("REMOVE_USER is FYI only, nothing to do...");
+            return {};
+        case USER_IDENTIFICATION_ASSOCIATION:
+            return onSetUserIdentificationAssociation(value);
+        default:
+            return Error(static_cast<int>(StatusCode::INVALID_ARG))
+                   << "Unsupported property: " << toString(value);
+    }
+}
+
+Result<std::unique_ptr<VehiclePropValue>> FakeUserHal::onGetProperty(
+        const VehiclePropValue& value) {
+    ALOGV("onGetProperty(%s)", toString(value).c_str());
+    switch (value.prop) {
+        case INITIAL_USER_INFO:
+        case SWITCH_USER:
+        case CREATE_USER:
+        case REMOVE_USER:
+            ALOGE("onGetProperty(): %d is only supported on SET", value.prop);
+            return Error(static_cast<int>(StatusCode::INVALID_ARG)) << "only supported on SET";
+        case USER_IDENTIFICATION_ASSOCIATION:
+            return onGetUserIdentificationAssociation(value);
+        default:
+            ALOGE("onGetProperty(): %d is not supported", value.prop);
+            return Error(static_cast<int>(StatusCode::INVALID_ARG)) << "not supported by User HAL";
+    }
+}
+
+Result<std::unique_ptr<VehiclePropValue>> FakeUserHal::onGetUserIdentificationAssociation(
+        const VehiclePropValue& value) {
+    if (mSetUserIdentificationAssociationResponseFromCmd == nullptr) {
+        return defaultUserIdentificationAssociation(value);
+    }
+    ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s",
+          toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
+    auto newValue = std::unique_ptr<VehiclePropValue>(
+            new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
+    auto requestId = getRequestId(value);
+    if (requestId.ok()) {
+        // Must use the same requestId
+        newValue->value.int32Values[0] = *requestId;
+    } else {
+        ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s", toString(value).c_str());
+    }
+    return newValue;
+}
+
+Result<std::unique_ptr<VehiclePropValue>> FakeUserHal::onSetInitialUserInfoResponse(
+        const VehiclePropValue& value) {
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(INITIAL_USER_INFO): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
+    }
+
+    if (value.areaId != 0) {
+        ALOGD("set(INITIAL_USER_INFO) called from lshal; storing it: %s", toString(value).c_str());
+        mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
+        return {};
+    }
+
+    ALOGD("set(INITIAL_USER_INFO) called from Android: %s", toString(value).c_str());
+    if (mInitialUserResponseFromCmd != nullptr) {
+        ALOGI("replying INITIAL_USER_INFO with lshal value:  %s",
+              toString(*mInitialUserResponseFromCmd).c_str());
+        return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), *requestId);
+    }
+
+    // Returns default response
+    auto updatedValue = user_hal_helper::toVehiclePropValue(InitialUserInfoResponse{
+            .requestId = *requestId,
+            .action = InitialUserInfoResponseAction::DEFAULT,
+    });
+    ALOGI("no lshal response; replying with InitialUserInfoResponseAction::DEFAULT: %s",
+          toString(*updatedValue).c_str());
+    return updatedValue;
+}
+
+Result<std::unique_ptr<VehiclePropValue>> FakeUserHal::onSetSwitchUserResponse(
+        const VehiclePropValue& value) {
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(SWITCH_USER): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
+    }
+
+    auto messageType = getSwitchUserMessageType(value);
+    if (!messageType.ok()) {
+        ALOGE("Failed to get messageType on set(SWITCH_USER): %s",
+              messageType.error().message().c_str());
+        return messageType.error();
+    }
+
+    if (value.areaId != 0) {
+        if (*messageType == SwitchUserMessageType::VEHICLE_REQUEST) {
+            // User HAL can also request a user switch, so we need to check it first
+            ALOGD("set(SWITCH_USER) called from lshal to emulate a vehicle request: %s",
+                  toString(value).c_str());
+            return std::unique_ptr<VehiclePropValue>(new VehiclePropValue(value));
+        }
+        // Otherwise, we store it
+        ALOGD("set(SWITCH_USER) called from lshal; storing it: %s", toString(value).c_str());
+        mSwitchUserResponseFromCmd.reset(new VehiclePropValue(value));
+        return {};
+    }
+    ALOGD("set(SWITCH_USER) called from Android: %s", toString(value).c_str());
+
+    if (mSwitchUserResponseFromCmd != nullptr) {
+        ALOGI("replying SWITCH_USER with lshal value:  %s",
+              toString(*mSwitchUserResponseFromCmd).c_str());
+        return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), *requestId);
+    }
+
+    if (*messageType == SwitchUserMessageType::LEGACY_ANDROID_SWITCH ||
+        *messageType == SwitchUserMessageType::ANDROID_POST_SWITCH) {
+        ALOGI("request is %s; ignoring it", toString(*messageType).c_str());
+        return {};
+    }
+
+    // Returns default response
+    auto updatedValue = user_hal_helper::toVehiclePropValue(SwitchUserResponse{
+            .requestId = *requestId,
+            .messageType = SwitchUserMessageType::VEHICLE_RESPONSE,
+            .status = SwitchUserStatus::SUCCESS,
+    });
+    ALOGI("no lshal response; replying with VEHICLE_RESPONSE / SUCCESS: %s",
+          toString(*updatedValue).c_str());
+    return updatedValue;
+}
+
+Result<std::unique_ptr<VehiclePropValue>> FakeUserHal::onSetCreateUserResponse(
+        const VehiclePropValue& value) {
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(CREATE_USER): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
+    }
+
+    if (value.areaId != 0) {
+        ALOGD("set(CREATE_USER) called from lshal; storing it: %s", toString(value).c_str());
+        mCreateUserResponseFromCmd.reset(new VehiclePropValue(value));
+        return {};
+    }
+    ALOGD("set(CREATE_USER) called from Android: %s", toString(value).c_str());
+
+    if (mCreateUserResponseFromCmd != nullptr) {
+        ALOGI("replying CREATE_USER with lshal value:  %s",
+              toString(*mCreateUserResponseFromCmd).c_str());
+        return sendUserHalResponse(std::move(mCreateUserResponseFromCmd), *requestId);
+    }
+
+    // Returns default response
+    auto updatedValue = user_hal_helper::toVehiclePropValue(CreateUserResponse{
+            .requestId = *requestId,
+            .status = CreateUserStatus::SUCCESS,
+    });
+    ALOGI("no lshal response; replying with SUCCESS: %s", toString(*updatedValue).c_str());
+    return updatedValue;
+}
+
+Result<std::unique_ptr<VehiclePropValue>> FakeUserHal::onSetUserIdentificationAssociation(
+        const VehiclePropValue& value) {
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(USER_IDENTIFICATION_ASSOCIATION): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
+    }
+
+    if (value.areaId != 0) {
+        ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from lshal; storing it: %s",
+              toString(value).c_str());
+        mSetUserIdentificationAssociationResponseFromCmd.reset(new VehiclePropValue(value));
+        return {};
+    }
+    ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from Android: %s", toString(value).c_str());
+
+    if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
+        ALOGI("replying USER_IDENTIFICATION_ASSOCIATION with lshal value:  %s",
+              toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
+        // Not moving response so it can be used on GET requests
+        auto copy = std::unique_ptr<VehiclePropValue>(
+                new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
+        return sendUserHalResponse(std::move(copy), *requestId);
+    }
+    // Returns default response
+    return defaultUserIdentificationAssociation(value);
+}
+
+Result<std::unique_ptr<VehiclePropValue>> FakeUserHal::defaultUserIdentificationAssociation(
+        const VehiclePropValue& request) {
+    // TODO(b/159498909): return a response with NOT_ASSOCIATED_ANY_USER for all requested types
+    ALOGE("no lshal response for %s; replying with NOT_AVAILABLE", toString(request).c_str());
+    return Error(static_cast<int>(StatusCode::NOT_AVAILABLE)) << "not set by lshal";
+}
+
+Result<std::unique_ptr<VehiclePropValue>> FakeUserHal::sendUserHalResponse(
+        std::unique_ptr<VehiclePropValue> response, int32_t requestId) {
+    switch (response->areaId) {
+        case 1:
+            ALOGD("returning response with right request id");
+            response->value.int32Values[0] = requestId;
+            break;
+        case 2:
+            ALOGD("returning response with wrong request id");
+            response->value.int32Values[0] = -requestId;
+            break;
+        case 3:
+            ALOGD("not generating a property change event because of lshal prop: %s",
+                  toString(*response).c_str());
+            return Error(static_cast<int>(StatusCode::NOT_AVAILABLE))
+                   << "not generating a property change event because of lshal prop: "
+                   << toString(*response);
+        default:
+            ALOGE("invalid action on lshal response: %s", toString(*response).c_str());
+            return Error(static_cast<int>(StatusCode::INTERNAL_ERROR))
+                   << "invalid action on lshal response: " << toString(*response);
+    }
+
+    ALOGD("updating property to: %s", toString(*response).c_str());
+    return response;
+}
+
+std::string FakeUserHal::showDumpHelp() {
+    return fmt::format("{}: dumps state used for user management\n", kUserHalDumpOption);
+}
+
+std::string FakeUserHal::dump(std::string indent) {
+    std::string info;
+    if (mInitialUserResponseFromCmd != nullptr) {
+        info += fmt::format("{}InitialUserInfo response: {}\n", indent.c_str(),
+                            toString(*mInitialUserResponseFromCmd).c_str());
+    } else {
+        info += fmt::format("{}No InitialUserInfo response\n", indent.c_str());
+    }
+    if (mSwitchUserResponseFromCmd != nullptr) {
+        info += fmt::format("{}SwitchUser response: {}\n", indent.c_str(),
+                            toString(*mSwitchUserResponseFromCmd).c_str());
+    } else {
+        info += fmt::format("{}No SwitchUser response\n", indent.c_str());
+    }
+    if (mCreateUserResponseFromCmd != nullptr) {
+        info += fmt::format("{}CreateUser response: {}\n", indent.c_str(),
+                            toString(*mCreateUserResponseFromCmd).c_str());
+    } else {
+        info += fmt::format("{}No CreateUser response\n", indent.c_str());
+    }
+    if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
+        info += fmt::format("{}SetUserIdentificationAssociation response: {}\n", indent.c_str(),
+                            toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
+    } else {
+        info += fmt::format("{}No SetUserIdentificationAssociation response\n", indent.c_str());
+    }
+    return info;
+}
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/include/FakeUserHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/include/FakeUserHal.h
new file mode 100644
index 0000000..122aee8
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/include/FakeUserHal.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_FakeUserHal_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_FakeUserHal_H_
+
+#include <android-base/format.h>
+#include <android-base/result.h>
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+constexpr char kUserHalDumpOption[] = "--user-hal";
+
+/**
+ * Class used to emulate a real User HAL behavior through lshal debug requests.
+ */
+class FakeUserHal {
+  public:
+    FakeUserHal() {}
+
+    ~FakeUserHal() = default;
+
+    /**
+     * Checks if the emulator can handle the property.
+     */
+    bool isSupported(int32_t prop);
+
+    /**
+     * Lets the emulator set the property.
+     *
+     * @return updated property and StatusCode
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetProperty(
+            const VehiclePropValue& value);
+
+    /**
+     * Gets the property value from the emulator.
+     *
+     * @return property value and StatusCode
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onGetProperty(
+            const VehiclePropValue& value);
+
+    /**
+     * Shows the User HAL emulation help.
+     */
+    std::string showDumpHelp();
+
+    /**
+     * Dump its contents.
+     */
+    std::string dump(std::string indent);
+
+  private:
+    /**
+     * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
+     * indicating what the initial user should be.
+     *
+     * During normal circumstances, the emulator will reply right away, passing a response if
+     * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which
+     * user to boot).
+     *
+     * But during development / testing, the behavior can be changed using lshal dump, which must
+     * use the areaId to indicate what should happen next.
+     *
+     * So, the behavior of set(INITIAL_USER_INFO) is:
+     *
+     * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called
+     * by lshal).
+     * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id
+     * and InitialUserInfoResponseAction::DEFAULT
+     * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
+     * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
+     * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can
+     * test this error scenario)
+     * - if it's 3, then don't send a property change (so Android can emulate a timeout)
+     *
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetInitialUserInfoResponse(
+            const VehiclePropValue& value);
+
+    /**
+     * Used to emulate SWITCH_USER - see onSetInitialUserInfoResponse() for usage.
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetSwitchUserResponse(
+            const VehiclePropValue& value);
+
+    /**
+     * Used to emulate CREATE_USER - see onSetInitialUserInfoResponse() for usage.
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetCreateUserResponse(
+            const VehiclePropValue& value);
+
+    /**
+     * Used to emulate set USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
+     * usage.
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetUserIdentificationAssociation(
+            const VehiclePropValue& value);
+
+    /**
+     * Used to emulate get USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
+     * usage.
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onGetUserIdentificationAssociation(
+            const VehiclePropValue& value);
+
+    /**
+     * Creates a default USER_IDENTIFICATION_ASSOCIATION when it was not set by lshal.
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> defaultUserIdentificationAssociation(
+            const VehiclePropValue& request);
+
+    android::base::Result<std::unique_ptr<VehiclePropValue>> sendUserHalResponse(
+            std::unique_ptr<VehiclePropValue> response, int32_t requestId);
+
+    std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
+    std::unique_ptr<VehiclePropValue> mSwitchUserResponseFromCmd;
+    std::unique_ptr<VehiclePropValue> mCreateUserResponseFromCmd;
+    std::unique_ptr<VehiclePropValue> mSetUserIdentificationAssociationResponseFromCmd;
+};
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_FakeUserHal_H_
diff --git a/automotive/vehicle/2.0/default/tests/RecurrentTimer_test.cpp b/automotive/vehicle/2.0/default/tests/RecurrentTimer_test.cpp
index 9fc17c6..d7547f6 100644
--- a/automotive/vehicle/2.0/default/tests/RecurrentTimer_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/RecurrentTimer_test.cpp
@@ -41,7 +41,8 @@
 
     timer.registerRecurrentEvent(milliseconds(1), 0xdead);
     std::this_thread::sleep_for(milliseconds(100));
-    ASSERT_EQ_WITH_TOLERANCE(100, counter.load(), 20);
+    // This test is unstable, so set the tolerance to 50.
+    ASSERT_EQ_WITH_TOLERANCE(100, counter.load(), 50);
 }
 
 TEST(RecurrentTimerTest, multipleIntervals) {
@@ -66,7 +67,8 @@
     timer.registerRecurrentEvent(milliseconds(5), 0xbeef);
 
     std::this_thread::sleep_for(milliseconds(100));
-    ASSERT_EQ_WITH_TOLERANCE(100, counter1ms.load(), 20);
+    // This test is unstable, so set the tolerance to 50.
+    ASSERT_EQ_WITH_TOLERANCE(100, counter1ms.load(), 50);
     ASSERT_EQ_WITH_TOLERANCE(20, counter5ms.load(), 5);
 }
 
diff --git a/automotive/vehicle/2.0/default/tests/VehicleObjectPool_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleObjectPool_test.cpp
index 4e3ade1..0968166 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleObjectPool_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleObjectPool_test.cpp
@@ -58,10 +58,12 @@
 
 TEST_F(VehicleObjectPoolTest, valuePoolBasicCorrectness) {
     auto value = valuePool->obtain(VehiclePropertyType::INT32);
-    // At this point, v1 should be recycled and the only object in the pool.
-    ASSERT_EQ(value.get(), valuePool->obtain(VehiclePropertyType::INT32).get());
+    void* raw = value.get();
+    value.reset();
+    // At this point, value should be recycled and the only object in the pool.
+    ASSERT_EQ(raw, valuePool->obtain(VehiclePropertyType::INT32).get());
     // Obtaining value of another type - should return a new object
-    ASSERT_NE(value.get(), valuePool->obtain(VehiclePropertyType::FLOAT).get());
+    ASSERT_NE(raw, valuePool->obtain(VehiclePropertyType::FLOAT).get());
 
     ASSERT_EQ(3u, stats->Obtained);
     ASSERT_EQ(2u, stats->Created);
diff --git a/automotive/vehicle/TEST_MAPPING b/automotive/vehicle/TEST_MAPPING
new file mode 100644
index 0000000..ff6f3be
--- /dev/null
+++ b/automotive/vehicle/TEST_MAPPING
@@ -0,0 +1,28 @@
+{
+  "presubmit": [
+    {
+      "name": "VehicleHalAidlHidlCompatibilityTest"
+    },
+    {
+      "name": "VehicleHalDefaultConfigTest"
+    },
+    {
+      "name": "VehicleHalVehicleUtilsTest"
+    },
+    {
+      "name": "FakeVehicleHardwareTest"
+    },
+    {
+      "name": "FakeVehicleHalValueGeneratorsTest"
+    },
+    {
+      "name": "FakeObd2FrameTest"
+    },
+    {
+      "name": "FakeUserHalTest"
+    },
+    {
+      "name": "DefaultVehicleHalTest"
+    }
+  ]
+}
diff --git a/automotive/vehicle/aidl/Android.bp b/automotive/vehicle/aidl/Android.bp
new file mode 100644
index 0000000..1ca62ac
--- /dev/null
+++ b/automotive/vehicle/aidl/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.automotive.vehicle",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/automotive/vehicle/**/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+            min_sdk_version: "31",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.car.framework",
+            ],
+        },
+    },
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CreateUserRequest.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CreateUserRequest.aidl
new file mode 100644
index 0000000..22c690c
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CreateUserRequest.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable CreateUserRequest {
+  int requestId;
+  android.hardware.automotive.vehicle.UserInfo newUserInfo;
+  @utf8InCpp String newUserName;
+  android.hardware.automotive.vehicle.UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CreateUserResponse.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CreateUserResponse.aidl
new file mode 100644
index 0000000..7d0196b
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CreateUserResponse.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable CreateUserResponse {
+  int requestId;
+  android.hardware.automotive.vehicle.CreateUserStatus status = android.hardware.automotive.vehicle.CreateUserStatus.SUCCESS;
+  @utf8InCpp String errorMessage;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CreateUserStatus.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CreateUserStatus.aidl
new file mode 100644
index 0000000..4c3b751
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CreateUserStatus.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum CreateUserStatus {
+  SUCCESS = 1,
+  FAILURE = 2,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CustomInputType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CustomInputType.aidl
new file mode 100644
index 0000000..4decb69
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/CustomInputType.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum CustomInputType {
+  CUSTOM_EVENT_F1 = 1001,
+  CUSTOM_EVENT_F2 = 1002,
+  CUSTOM_EVENT_F3 = 1003,
+  CUSTOM_EVENT_F4 = 1004,
+  CUSTOM_EVENT_F5 = 1005,
+  CUSTOM_EVENT_F6 = 1006,
+  CUSTOM_EVENT_F7 = 1007,
+  CUSTOM_EVENT_F8 = 1008,
+  CUSTOM_EVENT_F9 = 1009,
+  CUSTOM_EVENT_F10 = 1010,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.aidl
new file mode 100644
index 0000000..9704704
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.aidl
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible 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.vehicle;
+@Backing(type="int") @VintfStability
+enum DiagnosticFloatSensorIndex {
+  CALCULATED_ENGINE_LOAD = 0,
+  ENGINE_COOLANT_TEMPERATURE = 1,
+  SHORT_TERM_FUEL_TRIM_BANK1 = 2,
+  LONG_TERM_FUEL_TRIM_BANK1 = 3,
+  SHORT_TERM_FUEL_TRIM_BANK2 = 4,
+  LONG_TERM_FUEL_TRIM_BANK2 = 5,
+  FUEL_PRESSURE = 6,
+  INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 7,
+  ENGINE_RPM = 8,
+  VEHICLE_SPEED = 9,
+  TIMING_ADVANCE = 10,
+  MAF_AIR_FLOW_RATE = 11,
+  THROTTLE_POSITION = 12,
+  OXYGEN_SENSOR1_VOLTAGE = 13,
+  OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM = 14,
+  OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO = 15,
+  OXYGEN_SENSOR2_VOLTAGE = 16,
+  OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM = 17,
+  OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO = 18,
+  OXYGEN_SENSOR3_VOLTAGE = 19,
+  OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM = 20,
+  OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO = 21,
+  OXYGEN_SENSOR4_VOLTAGE = 22,
+  OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM = 23,
+  OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO = 24,
+  OXYGEN_SENSOR5_VOLTAGE = 25,
+  OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM = 26,
+  OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO = 27,
+  OXYGEN_SENSOR6_VOLTAGE = 28,
+  OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM = 29,
+  OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO = 30,
+  OXYGEN_SENSOR7_VOLTAGE = 31,
+  OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM = 32,
+  OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO = 33,
+  OXYGEN_SENSOR8_VOLTAGE = 34,
+  OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM = 35,
+  OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO = 36,
+  FUEL_RAIL_PRESSURE = 37,
+  FUEL_RAIL_GAUGE_PRESSURE = 38,
+  COMMANDED_EXHAUST_GAS_RECIRCULATION = 39,
+  EXHAUST_GAS_RECIRCULATION_ERROR = 40,
+  COMMANDED_EVAPORATIVE_PURGE = 41,
+  FUEL_TANK_LEVEL_INPUT = 42,
+  EVAPORATION_SYSTEM_VAPOR_PRESSURE = 43,
+  CATALYST_TEMPERATURE_BANK1_SENSOR1 = 44,
+  CATALYST_TEMPERATURE_BANK2_SENSOR1 = 45,
+  CATALYST_TEMPERATURE_BANK1_SENSOR2 = 46,
+  CATALYST_TEMPERATURE_BANK2_SENSOR2 = 47,
+  ABSOLUTE_LOAD_VALUE = 48,
+  FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO = 49,
+  RELATIVE_THROTTLE_POSITION = 50,
+  ABSOLUTE_THROTTLE_POSITION_B = 51,
+  ABSOLUTE_THROTTLE_POSITION_C = 52,
+  ACCELERATOR_PEDAL_POSITION_D = 53,
+  ACCELERATOR_PEDAL_POSITION_E = 54,
+  ACCELERATOR_PEDAL_POSITION_F = 55,
+  COMMANDED_THROTTLE_ACTUATOR = 56,
+  ETHANOL_FUEL_PERCENTAGE = 57,
+  ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58,
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59,
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60,
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62,
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63,
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64,
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 65,
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 66,
+  RELATIVE_ACCELERATOR_PEDAL_POSITION = 67,
+  HYBRID_BATTERY_PACK_REMAINING_LIFE = 68,
+  FUEL_INJECTION_TIMING = 69,
+  ENGINE_FUEL_RATE = 70,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.aidl
new file mode 100644
index 0000000..b3f13d4
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.aidl
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible 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.vehicle;
+@Backing(type="int") @VintfStability
+enum DiagnosticIntegerSensorIndex {
+  FUEL_SYSTEM_STATUS = 0,
+  MALFUNCTION_INDICATOR_LIGHT_ON = 1,
+  IGNITION_MONITORS_SUPPORTED = 2,
+  IGNITION_SPECIFIC_MONITORS = 3,
+  INTAKE_AIR_TEMPERATURE = 4,
+  COMMANDED_SECONDARY_AIR_STATUS = 5,
+  NUM_OXYGEN_SENSORS_PRESENT = 6,
+  RUNTIME_SINCE_ENGINE_START = 7,
+  DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 8,
+  WARMUPS_SINCE_CODES_CLEARED = 9,
+  DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 10,
+  ABSOLUTE_BAROMETRIC_PRESSURE = 11,
+  CONTROL_MODULE_VOLTAGE = 12,
+  AMBIENT_AIR_TEMPERATURE = 13,
+  TIME_WITH_MALFUNCTION_LIGHT_ON = 14,
+  TIME_SINCE_TROUBLE_CODES_CLEARED = 15,
+  MAX_FUEL_AIR_EQUIVALENCE_RATIO = 16,
+  MAX_OXYGEN_SENSOR_VOLTAGE = 17,
+  MAX_OXYGEN_SENSOR_CURRENT = 18,
+  MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 19,
+  MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 20,
+  FUEL_TYPE = 21,
+  FUEL_RAIL_ABSOLUTE_PRESSURE = 22,
+  ENGINE_OIL_TEMPERATURE = 23,
+  DRIVER_DEMAND_PERCENT_TORQUE = 24,
+  ENGINE_ACTUAL_PERCENT_TORQUE = 25,
+  ENGINE_REFERENCE_PERCENT_TORQUE = 26,
+  ENGINE_PERCENT_TORQUE_DATA_IDLE = 27,
+  ENGINE_PERCENT_TORQUE_DATA_POINT1 = 28,
+  ENGINE_PERCENT_TORQUE_DATA_POINT2 = 29,
+  ENGINE_PERCENT_TORQUE_DATA_POINT3 = 30,
+  ENGINE_PERCENT_TORQUE_DATA_POINT4 = 31,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/ElectronicTollCollectionCardStatus.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/ElectronicTollCollectionCardStatus.aidl
new file mode 100644
index 0000000..9772aee
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/ElectronicTollCollectionCardStatus.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum ElectronicTollCollectionCardStatus {
+  UNKNOWN = 0,
+  ELECTRONIC_TOLL_COLLECTION_CARD_VALID = 1,
+  ELECTRONIC_TOLL_COLLECTION_CARD_INVALID = 2,
+  ELECTRONIC_TOLL_COLLECTION_CARD_NOT_INSERTED = 3,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/ElectronicTollCollectionCardType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/ElectronicTollCollectionCardType.aidl
new file mode 100644
index 0000000..22cf2c3
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/ElectronicTollCollectionCardType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum ElectronicTollCollectionCardType {
+  UNKNOWN = 0,
+  JP_ELECTRONIC_TOLL_COLLECTION_CARD = 1,
+  JP_ELECTRONIC_TOLL_COLLECTION_CARD_V2 = 2,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvConnectorType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvConnectorType.aidl
new file mode 100644
index 0000000..b469578
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvConnectorType.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum EvConnectorType {
+  UNKNOWN = 0,
+  IEC_TYPE_1_AC = 1,
+  IEC_TYPE_2_AC = 2,
+  IEC_TYPE_3_AC = 3,
+  IEC_TYPE_4_DC = 4,
+  IEC_TYPE_1_CCS_DC = 5,
+  IEC_TYPE_2_CCS_DC = 6,
+  TESLA_ROADSTER = 7,
+  TESLA_HPWC = 8,
+  TESLA_SUPERCHARGER = 9,
+  GBT_AC = 10,
+  GBT_DC = 11,
+  OTHER = 101,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvsServiceRequestIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvsServiceRequestIndex.aidl
new file mode 100644
index 0000000..2fdb9b5
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvsServiceRequestIndex.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum EvsServiceRequestIndex {
+  TYPE = 0,
+  STATE = 1,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvsServiceState.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvsServiceState.aidl
new file mode 100644
index 0000000..df81ee7
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvsServiceState.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum EvsServiceState {
+  OFF = 0,
+  ON = 1,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvsServiceType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvsServiceType.aidl
new file mode 100644
index 0000000..1363a64
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/EvsServiceType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum EvsServiceType {
+  REARVIEW = 0,
+  SURROUNDVIEW = 1,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/FuelType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/FuelType.aidl
new file mode 100644
index 0000000..14bb61b
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/FuelType.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum FuelType {
+  FUEL_TYPE_UNKNOWN = 0,
+  FUEL_TYPE_UNLEADED = 1,
+  FUEL_TYPE_LEADED = 2,
+  FUEL_TYPE_DIESEL_1 = 3,
+  FUEL_TYPE_DIESEL_2 = 4,
+  FUEL_TYPE_BIODIESEL = 5,
+  FUEL_TYPE_E85 = 6,
+  FUEL_TYPE_LPG = 7,
+  FUEL_TYPE_CNG = 8,
+  FUEL_TYPE_LNG = 9,
+  FUEL_TYPE_ELECTRIC = 10,
+  FUEL_TYPE_HYDROGEN = 11,
+  FUEL_TYPE_OTHER = 12,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueRequest.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueRequest.aidl
new file mode 100644
index 0000000..d88cd8b
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueRequest.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable GetValueRequest {
+  long requestId;
+  android.hardware.automotive.vehicle.VehiclePropValue prop;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueRequests.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueRequests.aidl
new file mode 100644
index 0000000..a7df2ff
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueRequests.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable GetValueRequests {
+  android.hardware.automotive.vehicle.GetValueRequest[] payloads;
+  @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueResult.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueResult.aidl
new file mode 100644
index 0000000..25f3575
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueResult.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable GetValueResult {
+  long requestId;
+  android.hardware.automotive.vehicle.StatusCode status = android.hardware.automotive.vehicle.StatusCode.OK;
+  @nullable android.hardware.automotive.vehicle.VehiclePropValue prop;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueResults.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueResults.aidl
new file mode 100644
index 0000000..4c365b1
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/GetValueResults.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable GetValueResults {
+  android.hardware.automotive.vehicle.GetValueResult[] payloads;
+  @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicle.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicle.aidl
new file mode 100644
index 0000000..b5f62aa
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicle.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@VintfStability
+interface IVehicle {
+  android.hardware.automotive.vehicle.VehiclePropConfigs getAllPropConfigs();
+  android.hardware.automotive.vehicle.VehiclePropConfigs getPropConfigs(in int[] props);
+  void getValues(android.hardware.automotive.vehicle.IVehicleCallback callback, in android.hardware.automotive.vehicle.GetValueRequests requests);
+  void setValues(android.hardware.automotive.vehicle.IVehicleCallback callback, in android.hardware.automotive.vehicle.SetValueRequests requests);
+  void subscribe(in android.hardware.automotive.vehicle.IVehicleCallback callback, in android.hardware.automotive.vehicle.SubscribeOptions[] options, int maxSharedMemoryFileCount);
+  void unsubscribe(in android.hardware.automotive.vehicle.IVehicleCallback callback, in int[] propIds);
+  void returnSharedMemory(in android.hardware.automotive.vehicle.IVehicleCallback callback, long sharedMemoryId);
+  const long INVALID_MEMORY_ID = 0;
+  const int MAX_SHARED_MEMORY_FILES_PER_CLIENT = 3;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicleCallback.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicleCallback.aidl
new file mode 100644
index 0000000..2c5a333
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/IVehicleCallback.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@VintfStability
+interface IVehicleCallback {
+  oneway void onGetValues(in android.hardware.automotive.vehicle.GetValueResults responses);
+  oneway void onSetValues(in android.hardware.automotive.vehicle.SetValueResults responses);
+  oneway void onPropertyEvent(in android.hardware.automotive.vehicle.VehiclePropValues propValues, int sharedMemoryFileCount);
+  oneway void onPropertySetError(in android.hardware.automotive.vehicle.VehiclePropErrors errors);
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoRequest.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoRequest.aidl
new file mode 100644
index 0000000..a4c048a
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoRequest.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable InitialUserInfoRequest {
+  int requestId;
+  android.hardware.automotive.vehicle.InitialUserInfoRequestType requestType = android.hardware.automotive.vehicle.InitialUserInfoRequestType.UNKNOWN;
+  android.hardware.automotive.vehicle.UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoRequestType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoRequestType.aidl
new file mode 100644
index 0000000..51260fa
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoRequestType.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum InitialUserInfoRequestType {
+  UNKNOWN = 0,
+  FIRST_BOOT = 1,
+  FIRST_BOOT_AFTER_OTA = 2,
+  COLD_BOOT = 3,
+  RESUME = 4,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoResponse.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoResponse.aidl
new file mode 100644
index 0000000..f0e1612
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoResponse.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable InitialUserInfoResponse {
+  int requestId;
+  android.hardware.automotive.vehicle.InitialUserInfoResponseAction action = android.hardware.automotive.vehicle.InitialUserInfoResponseAction.DEFAULT;
+  android.hardware.automotive.vehicle.UserInfo userToSwitchOrCreate;
+  @utf8InCpp String userLocales;
+  @utf8InCpp String userNameToCreate;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoResponseAction.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoResponseAction.aidl
new file mode 100644
index 0000000..d654b5c
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/InitialUserInfoResponseAction.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum InitialUserInfoResponseAction {
+  DEFAULT = 0,
+  SWITCH = 1,
+  CREATE = 2,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.aidl
new file mode 100644
index 0000000..73d4a14
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum Obd2CommonIgnitionMonitors {
+  COMPONENTS_AVAILABLE = 1,
+  COMPONENTS_INCOMPLETE = 2,
+  FUEL_SYSTEM_AVAILABLE = 4,
+  FUEL_SYSTEM_INCOMPLETE = 8,
+  MISFIRE_AVAILABLE = 16,
+  MISFIRE_INCOMPLETE = 32,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2CompressionIgnitionMonitors.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2CompressionIgnitionMonitors.aidl
new file mode 100644
index 0000000..01104c1
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2CompressionIgnitionMonitors.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum Obd2CompressionIgnitionMonitors {
+  COMPONENTS_AVAILABLE = 1,
+  COMPONENTS_INCOMPLETE = 2,
+  FUEL_SYSTEM_AVAILABLE = 4,
+  FUEL_SYSTEM_INCOMPLETE = 8,
+  MISFIRE_AVAILABLE = 16,
+  MISFIRE_INCOMPLETE = 32,
+  EGR_OR_VVT_AVAILABLE = 64,
+  EGR_OR_VVT_INCOMPLETE = 128,
+  PM_FILTER_AVAILABLE = 256,
+  PM_FILTER_INCOMPLETE = 512,
+  EXHAUST_GAS_SENSOR_AVAILABLE = 1024,
+  EXHAUST_GAS_SENSOR_INCOMPLETE = 2048,
+  BOOST_PRESSURE_AVAILABLE = 4096,
+  BOOST_PRESSURE_INCOMPLETE = 8192,
+  NOx_SCR_AVAILABLE = 16384,
+  NOx_SCR_INCOMPLETE = 32768,
+  NMHC_CATALYST_AVAILABLE = 65536,
+  NMHC_CATALYST_INCOMPLETE = 131072,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.aidl
new file mode 100644
index 0000000..9d588ea
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum Obd2FuelSystemStatus {
+  OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1,
+  CLOSED_LOOP = 2,
+  OPEN_ENGINE_LOAD_OR_DECELERATION = 4,
+  OPEN_SYSTEM_FAILURE = 8,
+  CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2FuelType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2FuelType.aidl
new file mode 100644
index 0000000..3ab3920
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2FuelType.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum Obd2FuelType {
+  NOT_AVAILABLE = 0,
+  GASOLINE = 1,
+  METHANOL = 2,
+  ETHANOL = 3,
+  DIESEL = 4,
+  LPG = 5,
+  CNG = 6,
+  PROPANE = 7,
+  ELECTRIC = 8,
+  BIFUEL_RUNNING_GASOLINE = 9,
+  BIFUEL_RUNNING_METHANOL = 10,
+  BIFUEL_RUNNING_ETHANOL = 11,
+  BIFUEL_RUNNING_LPG = 12,
+  BIFUEL_RUNNING_CNG = 13,
+  BIFUEL_RUNNING_PROPANE = 14,
+  BIFUEL_RUNNING_ELECTRIC = 15,
+  BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16,
+  HYBRID_GASOLINE = 17,
+  HYBRID_ETHANOL = 18,
+  HYBRID_DIESEL = 19,
+  HYBRID_ELECTRIC = 20,
+  HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21,
+  HYBRID_REGENERATIVE = 22,
+  BIFUEL_RUNNING_DIESEL = 23,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2IgnitionMonitorKind.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2IgnitionMonitorKind.aidl
new file mode 100644
index 0000000..ec8f1c2
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2IgnitionMonitorKind.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum Obd2IgnitionMonitorKind {
+  SPARK = 0,
+  COMPRESSION = 1,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2SecondaryAirStatus.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2SecondaryAirStatus.aidl
new file mode 100644
index 0000000..7f445bf
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2SecondaryAirStatus.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum Obd2SecondaryAirStatus {
+  UPSTREAM = 1,
+  DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2,
+  FROM_OUTSIDE_OR_OFF = 4,
+  PUMP_ON_FOR_DIAGNOSTICS = 8,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2SparkIgnitionMonitors.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2SparkIgnitionMonitors.aidl
new file mode 100644
index 0000000..badc29c
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/Obd2SparkIgnitionMonitors.aidl
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum Obd2SparkIgnitionMonitors {
+  COMPONENTS_AVAILABLE = 1,
+  COMPONENTS_INCOMPLETE = 2,
+  FUEL_SYSTEM_AVAILABLE = 4,
+  FUEL_SYSTEM_INCOMPLETE = 8,
+  MISFIRE_AVAILABLE = 16,
+  MISFIRE_INCOMPLETE = 32,
+  EGR_AVAILABLE = 64,
+  EGR_INCOMPLETE = 128,
+  OXYGEN_SENSOR_HEATER_AVAILABLE = 256,
+  OXYGEN_SENSOR_HEATER_INCOMPLETE = 512,
+  OXYGEN_SENSOR_AVAILABLE = 1024,
+  OXYGEN_SENSOR_INCOMPLETE = 2048,
+  AC_REFRIGERANT_AVAILABLE = 4096,
+  AC_REFRIGERANT_INCOMPLETE = 8192,
+  SECONDARY_AIR_SYSTEM_AVAILABLE = 16384,
+  SECONDARY_AIR_SYSTEM_INCOMPLETE = 32768,
+  EVAPORATIVE_SYSTEM_AVAILABLE = 65536,
+  EVAPORATIVE_SYSTEM_INCOMPLETE = 131072,
+  HEATED_CATALYST_AVAILABLE = 262144,
+  HEATED_CATALYST_INCOMPLETE = 524288,
+  CATALYST_AVAILABLE = 1048576,
+  CATALYST_INCOMPLETE = 2097152,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/PortLocationType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/PortLocationType.aidl
new file mode 100644
index 0000000..b831c7e
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/PortLocationType.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum PortLocationType {
+  UNKNOWN = 0,
+  FRONT_LEFT = 1,
+  FRONT_RIGHT = 2,
+  REAR_RIGHT = 3,
+  REAR_LEFT = 4,
+  FRONT = 5,
+  REAR = 6,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/ProcessTerminationReason.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/ProcessTerminationReason.aidl
new file mode 100644
index 0000000..f2838ad
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/ProcessTerminationReason.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum ProcessTerminationReason {
+  NOT_RESPONDING = 1,
+  IO_OVERUSE = 2,
+  MEMORY_OVERUSE = 3,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/RawPropValues.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/RawPropValues.aidl
new file mode 100644
index 0000000..e7b0a13
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/RawPropValues.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable RawPropValues {
+  int[] int32Values = {};
+  float[] floatValues;
+  long[] int64Values;
+  byte[] byteValues;
+  @utf8InCpp String stringValue;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/RemoveUserRequest.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/RemoveUserRequest.aidl
new file mode 100644
index 0000000..74457b9
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/RemoveUserRequest.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable RemoveUserRequest {
+  int requestId;
+  android.hardware.automotive.vehicle.UserInfo removedUserInfo;
+  android.hardware.automotive.vehicle.UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/RotaryInputType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/RotaryInputType.aidl
new file mode 100644
index 0000000..ff90034
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/RotaryInputType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum RotaryInputType {
+  ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION = 0,
+  ROTARY_INPUT_TYPE_AUDIO_VOLUME = 1,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueRequest.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueRequest.aidl
new file mode 100644
index 0000000..6a65307
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueRequest.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SetValueRequest {
+  long requestId;
+  android.hardware.automotive.vehicle.VehiclePropValue value;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueRequests.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueRequests.aidl
new file mode 100644
index 0000000..15fd7ea
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueRequests.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SetValueRequests {
+  android.hardware.automotive.vehicle.SetValueRequest[] payloads;
+  @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueResult.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueResult.aidl
new file mode 100644
index 0000000..ec5fabb
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SetValueResult {
+  long requestId;
+  android.hardware.automotive.vehicle.StatusCode status = android.hardware.automotive.vehicle.StatusCode.OK;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueResults.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueResults.aidl
new file mode 100644
index 0000000..47f1656
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SetValueResults.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SetValueResults {
+  android.hardware.automotive.vehicle.SetValueResult[] payloads;
+  @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/StatusCode.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/StatusCode.aidl
new file mode 100644
index 0000000..9b72412
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/StatusCode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum StatusCode {
+  OK = 0,
+  TRY_AGAIN = 1,
+  INVALID_ARG = 2,
+  NOT_AVAILABLE = 3,
+  ACCESS_DENIED = 4,
+  INTERNAL_ERROR = 5,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SubscribeOptions.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SubscribeOptions.aidl
new file mode 100644
index 0000000..91e7c14
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SubscribeOptions.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SubscribeOptions {
+  int propId;
+  int[] areaIds;
+  float sampleRate;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserMessageType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserMessageType.aidl
new file mode 100644
index 0000000..a3e59f1
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserMessageType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum SwitchUserMessageType {
+  UNKNOWN = 0,
+  LEGACY_ANDROID_SWITCH = 1,
+  ANDROID_SWITCH = 2,
+  VEHICLE_RESPONSE = 3,
+  VEHICLE_REQUEST = 4,
+  ANDROID_POST_SWITCH = 5,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserRequest.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserRequest.aidl
new file mode 100644
index 0000000..3012b7a
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserRequest.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SwitchUserRequest {
+  int requestId;
+  android.hardware.automotive.vehicle.SwitchUserMessageType messageType = android.hardware.automotive.vehicle.SwitchUserMessageType.UNKNOWN;
+  android.hardware.automotive.vehicle.UserInfo targetUser;
+  android.hardware.automotive.vehicle.UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserResponse.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserResponse.aidl
new file mode 100644
index 0000000..8915d1b
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserResponse.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SwitchUserResponse {
+  int requestId;
+  android.hardware.automotive.vehicle.SwitchUserMessageType messageType = android.hardware.automotive.vehicle.SwitchUserMessageType.UNKNOWN;
+  android.hardware.automotive.vehicle.SwitchUserStatus status = android.hardware.automotive.vehicle.SwitchUserStatus.SUCCESS;
+  @utf8InCpp String errorMessage;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserStatus.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserStatus.aidl
new file mode 100644
index 0000000..c7be9ec
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/SwitchUserStatus.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum SwitchUserStatus {
+  SUCCESS = 1,
+  FAILURE = 2,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociation.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociation.aidl
new file mode 100644
index 0000000..a540f8e
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociation.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable UserIdentificationAssociation {
+  android.hardware.automotive.vehicle.UserIdentificationAssociationType type = android.hardware.automotive.vehicle.UserIdentificationAssociationType.INVALID;
+  android.hardware.automotive.vehicle.UserIdentificationAssociationValue value = android.hardware.automotive.vehicle.UserIdentificationAssociationValue.UNKNOWN;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociationSetValue.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociationSetValue.aidl
new file mode 100644
index 0000000..1fd9ee8
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociationSetValue.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum UserIdentificationAssociationSetValue {
+  INVALID = 0,
+  ASSOCIATE_CURRENT_USER = 1,
+  DISASSOCIATE_CURRENT_USER = 2,
+  DISASSOCIATE_ALL_USERS = 3,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociationType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociationType.aidl
new file mode 100644
index 0000000..6498375
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociationType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum UserIdentificationAssociationType {
+  INVALID = 0,
+  KEY_FOB = 1,
+  CUSTOM_1 = 101,
+  CUSTOM_2 = 102,
+  CUSTOM_3 = 103,
+  CUSTOM_4 = 104,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociationValue.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociationValue.aidl
new file mode 100644
index 0000000..d5e0169
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationAssociationValue.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum UserIdentificationAssociationValue {
+  UNKNOWN = 1,
+  ASSOCIATED_CURRENT_USER = 2,
+  ASSOCIATED_ANOTHER_USER = 3,
+  NOT_ASSOCIATED_ANY_USER = 4,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationGetRequest.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationGetRequest.aidl
new file mode 100644
index 0000000..fe7fd6f
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationGetRequest.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable UserIdentificationGetRequest {
+  int requestId;
+  android.hardware.automotive.vehicle.UserInfo userInfo;
+  int numberAssociationTypes;
+  android.hardware.automotive.vehicle.UserIdentificationAssociationType[] associationTypes;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationResponse.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationResponse.aidl
new file mode 100644
index 0000000..3e2a257
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationResponse.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable UserIdentificationResponse {
+  int requestId;
+  int numberAssociation;
+  android.hardware.automotive.vehicle.UserIdentificationAssociation[] associations;
+  @utf8InCpp String errorMessage;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationSetAssociation.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationSetAssociation.aidl
new file mode 100644
index 0000000..57840fb
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationSetAssociation.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable UserIdentificationSetAssociation {
+  android.hardware.automotive.vehicle.UserIdentificationAssociationType type = android.hardware.automotive.vehicle.UserIdentificationAssociationType.INVALID;
+  android.hardware.automotive.vehicle.UserIdentificationAssociationSetValue value = android.hardware.automotive.vehicle.UserIdentificationAssociationSetValue.INVALID;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationSetRequest.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationSetRequest.aidl
new file mode 100644
index 0000000..db01b51
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserIdentificationSetRequest.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable UserIdentificationSetRequest {
+  int requestId;
+  android.hardware.automotive.vehicle.UserInfo userInfo;
+  int numberAssociations;
+  android.hardware.automotive.vehicle.UserIdentificationSetAssociation[] associations;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserInfo.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserInfo.aidl
new file mode 100644
index 0000000..f47d5e7
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UserInfo.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable UserInfo {
+  int userId = 0;
+  int flags;
+  const int USER_FLAG_SYSTEM = 1;
+  const int USER_FLAG_GUEST = 2;
+  const int USER_FLAG_EPHEMERAL = 4;
+  const int USER_FLAG_ADMIN = 8;
+  const int USER_FLAG_DISABLED = 16;
+  const int USER_FLAG_PROFILE = 32;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UsersInfo.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UsersInfo.aidl
new file mode 100644
index 0000000..edcef2e
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/UsersInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable UsersInfo {
+  android.hardware.automotive.vehicle.UserInfo currentUser;
+  int numberUsers;
+  android.hardware.automotive.vehicle.UserInfo[] existingUsers;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateConfigFlag.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateConfigFlag.aidl
new file mode 100644
index 0000000..7e48eba
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateConfigFlag.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleApPowerStateConfigFlag {
+  ENABLE_DEEP_SLEEP_FLAG = 1,
+  CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 2,
+  ENABLE_HIBERNATION_FLAG = 3,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateReport.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateReport.aidl
new file mode 100644
index 0000000..fc669ec
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateReport.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleApPowerStateReport {
+  WAIT_FOR_VHAL = 1,
+  DEEP_SLEEP_ENTRY = 2,
+  DEEP_SLEEP_EXIT = 3,
+  SHUTDOWN_POSTPONE = 4,
+  SHUTDOWN_START = 5,
+  ON = 6,
+  SHUTDOWN_PREPARE = 7,
+  SHUTDOWN_CANCELLED = 8,
+  HIBERNATION_ENTRY = 9,
+  HIBERNATION_EXIT = 10,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl
new file mode 100644
index 0000000..8b94d31
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleApPowerStateReq {
+  ON = 0,
+  SHUTDOWN_PREPARE = 1,
+  CANCEL_SHUTDOWN = 2,
+  FINISHED = 3,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateReqIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateReqIndex.aidl
new file mode 100644
index 0000000..f995c73
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateReqIndex.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleApPowerStateReqIndex {
+  STATE = 0,
+  ADDITIONAL = 1,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl
new file mode 100644
index 0000000..3fde1c7
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleApPowerStateShutdownParam {
+  SHUTDOWN_IMMEDIATELY = 1,
+  CAN_SLEEP = 2,
+  SHUTDOWN_ONLY = 3,
+  SLEEP_IMMEDIATELY = 4,
+  HIBERNATE_IMMEDIATELY = 5,
+  CAN_HIBERNATE = 6,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleArea.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleArea.aidl
new file mode 100644
index 0000000..4f8b917
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleArea.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleArea {
+  GLOBAL = 16777216,
+  WINDOW = 50331648,
+  MIRROR = 67108864,
+  SEAT = 83886080,
+  DOOR = 100663296,
+  WHEEL = 117440512,
+  MASK = 251658240,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
new file mode 100644
index 0000000..b93a11b
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable VehicleAreaConfig {
+  int areaId;
+  int minInt32Value;
+  int maxInt32Value;
+  long minInt64Value;
+  long maxInt64Value;
+  float minFloatValue;
+  float maxFloatValue;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaDoor.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaDoor.aidl
new file mode 100644
index 0000000..11139f9
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaDoor.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleAreaDoor {
+  ROW_1_LEFT = 1,
+  ROW_1_RIGHT = 4,
+  ROW_2_LEFT = 16,
+  ROW_2_RIGHT = 64,
+  ROW_3_LEFT = 256,
+  ROW_3_RIGHT = 1024,
+  HOOD = 268435456,
+  REAR = 536870912,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaMirror.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaMirror.aidl
new file mode 100644
index 0000000..c1e2fbd
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaMirror.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleAreaMirror {
+  DRIVER_LEFT = 1,
+  DRIVER_RIGHT = 2,
+  DRIVER_CENTER = 4,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
new file mode 100644
index 0000000..e76de32
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleAreaSeat {
+  ROW_1_LEFT = 1,
+  ROW_1_CENTER = 2,
+  ROW_1_RIGHT = 4,
+  ROW_2_LEFT = 16,
+  ROW_2_CENTER = 32,
+  ROW_2_RIGHT = 64,
+  ROW_3_LEFT = 256,
+  ROW_3_CENTER = 512,
+  ROW_3_RIGHT = 1024,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaWheel.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaWheel.aidl
new file mode 100644
index 0000000..9e83434
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaWheel.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleAreaWheel {
+  UNKNOWN = 0,
+  LEFT_FRONT = 1,
+  RIGHT_FRONT = 2,
+  LEFT_REAR = 4,
+  RIGHT_REAR = 8,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaWindow.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaWindow.aidl
new file mode 100644
index 0000000..6ec26fe
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaWindow.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleAreaWindow {
+  FRONT_WINDSHIELD = 1,
+  REAR_WINDSHIELD = 2,
+  ROW_1_LEFT = 16,
+  ROW_1_RIGHT = 64,
+  ROW_2_LEFT = 256,
+  ROW_2_RIGHT = 1024,
+  ROW_3_LEFT = 4096,
+  ROW_3_RIGHT = 16384,
+  ROOF_TOP_1 = 65536,
+  ROOF_TOP_2 = 131072,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleDisplay.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleDisplay.aidl
new file mode 100644
index 0000000..5aeafa4
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleDisplay.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleDisplay {
+  MAIN = 0,
+  INSTRUMENT_CLUSTER = 1,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleGear.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleGear.aidl
new file mode 100644
index 0000000..db4760d
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleGear.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleGear {
+  GEAR_UNKNOWN = 0,
+  GEAR_NEUTRAL = 1,
+  GEAR_REVERSE = 2,
+  GEAR_PARK = 4,
+  GEAR_DRIVE = 8,
+  GEAR_1 = 16,
+  GEAR_2 = 32,
+  GEAR_3 = 64,
+  GEAR_4 = 128,
+  GEAR_5 = 256,
+  GEAR_6 = 512,
+  GEAR_7 = 1024,
+  GEAR_8 = 2048,
+  GEAR_9 = 4096,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleHvacFanDirection.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleHvacFanDirection.aidl
new file mode 100644
index 0000000..a85751f
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleHvacFanDirection.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleHvacFanDirection {
+  UNKNOWN = 0,
+  FACE = 1,
+  FLOOR = 2,
+  FACE_AND_FLOOR = 3,
+  DEFROST = 4,
+  DEFROST_AND_FLOOR = 6,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.aidl
new file mode 100644
index 0000000..c4ac002
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleHwKeyInputAction {
+  ACTION_DOWN = 0,
+  ACTION_UP = 1,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl
new file mode 100644
index 0000000..09d5423
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleIgnitionState {
+  UNDEFINED = 0,
+  LOCK = 1,
+  OFF = 2,
+  ACC = 3,
+  ON = 4,
+  START = 5,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleLightState.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleLightState.aidl
new file mode 100644
index 0000000..d569851
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleLightState.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleLightState {
+  OFF = 0,
+  ON = 1,
+  DAYTIME_RUNNING = 2,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleLightSwitch.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleLightSwitch.aidl
new file mode 100644
index 0000000..0d3c636
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleLightSwitch.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleLightSwitch {
+  OFF = 0,
+  ON = 1,
+  DAYTIME_RUNNING = 2,
+  AUTOMATIC = 256,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleOilLevel.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleOilLevel.aidl
new file mode 100644
index 0000000..f2eb5aa
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleOilLevel.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleOilLevel {
+  CRITICALLY_LOW = 0,
+  LOW = 1,
+  NORMAL = 2,
+  HIGH = 3,
+  ERROR = 4,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropConfig.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropConfig.aidl
new file mode 100644
index 0000000..8602d2d
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropConfig.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable VehiclePropConfig {
+  int prop;
+  android.hardware.automotive.vehicle.VehiclePropertyAccess access = android.hardware.automotive.vehicle.VehiclePropertyAccess.NONE;
+  android.hardware.automotive.vehicle.VehiclePropertyChangeMode changeMode = android.hardware.automotive.vehicle.VehiclePropertyChangeMode.STATIC;
+  android.hardware.automotive.vehicle.VehicleAreaConfig[] areaConfigs;
+  int[] configArray;
+  @utf8InCpp String configString;
+  float minSampleRate;
+  float maxSampleRate;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropConfigs.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropConfigs.aidl
new file mode 100644
index 0000000..04c8006
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropConfigs.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable VehiclePropConfigs {
+  android.hardware.automotive.vehicle.VehiclePropConfig[] payloads;
+  @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropError.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropError.aidl
new file mode 100644
index 0000000..9835295
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropError.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable VehiclePropError {
+  int propId;
+  int areaId;
+  android.hardware.automotive.vehicle.StatusCode errorCode = android.hardware.automotive.vehicle.StatusCode.OK;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropErrors.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropErrors.aidl
new file mode 100644
index 0000000..9dcb10b
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropErrors.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable VehiclePropErrors {
+  android.hardware.automotive.vehicle.VehiclePropError[] payloads;
+  @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropValue.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropValue.aidl
new file mode 100644
index 0000000..c87379f
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropValue.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable VehiclePropValue {
+  long timestamp;
+  int areaId;
+  int prop;
+  android.hardware.automotive.vehicle.VehiclePropertyStatus status = android.hardware.automotive.vehicle.VehiclePropertyStatus.AVAILABLE;
+  android.hardware.automotive.vehicle.RawPropValues value;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropValues.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropValues.aidl
new file mode 100644
index 0000000..e09a6b9
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropValues.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable VehiclePropValues {
+  android.hardware.automotive.vehicle.VehiclePropValue[] payloads;
+  long sharedMemoryId;
+  @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
new file mode 100644
index 0000000..12126ea
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible 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.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleProperty {
+  INVALID = 0,
+  INFO_VIN = 286261504,
+  INFO_MAKE = 286261505,
+  INFO_MODEL = 286261506,
+  INFO_MODEL_YEAR = 289407235,
+  INFO_FUEL_CAPACITY = 291504388,
+  INFO_FUEL_TYPE = 289472773,
+  INFO_EV_BATTERY_CAPACITY = 291504390,
+  INFO_EV_CONNECTOR_TYPE = 289472775,
+  INFO_FUEL_DOOR_LOCATION = 289407240,
+  INFO_EV_PORT_LOCATION = 289407241,
+  INFO_DRIVER_SEAT = 356516106,
+  INFO_EXTERIOR_DIMENSIONS = 289472779,
+  INFO_MULTI_EV_PORT_LOCATIONS = 289472780,
+  PERF_ODOMETER = 291504644,
+  PERF_VEHICLE_SPEED = 291504647,
+  PERF_VEHICLE_SPEED_DISPLAY = 291504648,
+  PERF_STEERING_ANGLE = 291504649,
+  PERF_REAR_STEERING_ANGLE = 291504656,
+  ENGINE_COOLANT_TEMP = 291504897,
+  ENGINE_OIL_LEVEL = 289407747,
+  ENGINE_OIL_TEMP = 291504900,
+  ENGINE_RPM = 291504901,
+  WHEEL_TICK = 290521862,
+  FUEL_LEVEL = 291504903,
+  FUEL_DOOR_OPEN = 287310600,
+  EV_BATTERY_LEVEL = 291504905,
+  EV_CHARGE_PORT_OPEN = 287310602,
+  EV_CHARGE_PORT_CONNECTED = 287310603,
+  EV_BATTERY_INSTANTANEOUS_CHARGE_RATE = 291504908,
+  RANGE_REMAINING = 291504904,
+  TIRE_PRESSURE = 392168201,
+  CRITICALLY_LOW_TIRE_PRESSURE = 392168202,
+  GEAR_SELECTION = 289408000,
+  CURRENT_GEAR = 289408001,
+  PARKING_BRAKE_ON = 287310850,
+  PARKING_BRAKE_AUTO_APPLY = 287310851,
+  FUEL_LEVEL_LOW = 287310853,
+  NIGHT_MODE = 287310855,
+  TURN_SIGNAL_STATE = 289408008,
+  IGNITION_STATE = 289408009,
+  ABS_ACTIVE = 287310858,
+  TRACTION_CONTROL_ACTIVE = 287310859,
+  HVAC_FAN_SPEED = 356517120,
+  HVAC_FAN_DIRECTION = 356517121,
+  HVAC_TEMPERATURE_CURRENT = 358614274,
+  HVAC_TEMPERATURE_SET = 358614275,
+  HVAC_DEFROSTER = 320865540,
+  HVAC_AC_ON = 354419973,
+  HVAC_MAX_AC_ON = 354419974,
+  HVAC_MAX_DEFROST_ON = 354419975,
+  HVAC_RECIRC_ON = 354419976,
+  HVAC_DUAL_ON = 354419977,
+  HVAC_AUTO_ON = 354419978,
+  HVAC_SEAT_TEMPERATURE = 356517131,
+  HVAC_SIDE_MIRROR_HEAT = 339739916,
+  HVAC_STEERING_WHEEL_HEAT = 289408269,
+  HVAC_TEMPERATURE_DISPLAY_UNITS = 289408270,
+  HVAC_ACTUAL_FAN_SPEED_RPM = 356517135,
+  HVAC_POWER_ON = 354419984,
+  HVAC_FAN_DIRECTION_AVAILABLE = 356582673,
+  HVAC_AUTO_RECIRC_ON = 354419986,
+  HVAC_SEAT_VENTILATION = 356517139,
+  HVAC_ELECTRIC_DEFROSTER_ON = 320865556,
+  HVAC_TEMPERATURE_VALUE_SUGGESTION = 291570965,
+  DISTANCE_DISPLAY_UNITS = 289408512,
+  FUEL_VOLUME_DISPLAY_UNITS = 289408513,
+  TIRE_PRESSURE_DISPLAY_UNITS = 289408514,
+  EV_BATTERY_DISPLAY_UNITS = 289408515,
+  FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME = 287311364,
+  VEHICLE_SPEED_DISPLAY_UNITS = 289408517,
+  EXTERNAL_CAR_TIME = 290457096,
+  ANDROID_EPOCH_TIME = 290457094,
+  STORAGE_ENCRYPTION_BINDING_SEED = 292554247,
+  ENV_OUTSIDE_TEMPERATURE = 291505923,
+  AP_POWER_STATE_REQ = 289475072,
+  AP_POWER_STATE_REPORT = 289475073,
+  AP_POWER_BOOTUP_REASON = 289409538,
+  DISPLAY_BRIGHTNESS = 289409539,
+  HW_KEY_INPUT = 289475088,
+  HW_ROTARY_INPUT = 289475104,
+  HW_CUSTOM_INPUT = 289475120,
+  DOOR_POS = 373295872,
+  DOOR_MOVE = 373295873,
+  DOOR_LOCK = 371198722,
+  MIRROR_Z_POS = 339741504,
+  MIRROR_Z_MOVE = 339741505,
+  MIRROR_Y_POS = 339741506,
+  MIRROR_Y_MOVE = 339741507,
+  MIRROR_LOCK = 287312708,
+  MIRROR_FOLD = 287312709,
+  SEAT_MEMORY_SELECT = 356518784,
+  SEAT_MEMORY_SET = 356518785,
+  SEAT_BELT_BUCKLED = 354421634,
+  SEAT_BELT_HEIGHT_POS = 356518787,
+  SEAT_BELT_HEIGHT_MOVE = 356518788,
+  SEAT_FORE_AFT_POS = 356518789,
+  SEAT_FORE_AFT_MOVE = 356518790,
+  SEAT_BACKREST_ANGLE_1_POS = 356518791,
+  SEAT_BACKREST_ANGLE_1_MOVE = 356518792,
+  SEAT_BACKREST_ANGLE_2_POS = 356518793,
+  SEAT_BACKREST_ANGLE_2_MOVE = 356518794,
+  SEAT_HEIGHT_POS = 356518795,
+  SEAT_HEIGHT_MOVE = 356518796,
+  SEAT_DEPTH_POS = 356518797,
+  SEAT_DEPTH_MOVE = 356518798,
+  SEAT_TILT_POS = 356518799,
+  SEAT_TILT_MOVE = 356518800,
+  SEAT_LUMBAR_FORE_AFT_POS = 356518801,
+  SEAT_LUMBAR_FORE_AFT_MOVE = 356518802,
+  SEAT_LUMBAR_SIDE_SUPPORT_POS = 356518803,
+  SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 356518804,
+  SEAT_HEADREST_HEIGHT_POS = 289409941,
+  SEAT_HEADREST_HEIGHT_MOVE = 356518806,
+  SEAT_HEADREST_ANGLE_POS = 356518807,
+  SEAT_HEADREST_ANGLE_MOVE = 356518808,
+  SEAT_HEADREST_FORE_AFT_POS = 356518809,
+  SEAT_HEADREST_FORE_AFT_MOVE = 356518810,
+  SEAT_OCCUPANCY = 356518832,
+  WINDOW_POS = 322964416,
+  WINDOW_MOVE = 322964417,
+  WINDOW_LOCK = 320867268,
+  VEHICLE_MAP_SERVICE = 299895808,
+  OBD2_LIVE_FRAME = 299896064,
+  OBD2_FREEZE_FRAME = 299896065,
+  OBD2_FREEZE_FRAME_INFO = 299896066,
+  OBD2_FREEZE_FRAME_CLEAR = 299896067,
+  HEADLIGHTS_STATE = 289410560,
+  HIGH_BEAM_LIGHTS_STATE = 289410561,
+  FOG_LIGHTS_STATE = 289410562,
+  HAZARD_LIGHTS_STATE = 289410563,
+  HEADLIGHTS_SWITCH = 289410576,
+  HIGH_BEAM_LIGHTS_SWITCH = 289410577,
+  FOG_LIGHTS_SWITCH = 289410578,
+  HAZARD_LIGHTS_SWITCH = 289410579,
+  CABIN_LIGHTS_STATE = 289410817,
+  CABIN_LIGHTS_SWITCH = 289410818,
+  READING_LIGHTS_STATE = 356519683,
+  READING_LIGHTS_SWITCH = 356519684,
+  SUPPORT_CUSTOMIZE_VENDOR_PERMISSION = 287313669,
+  DISABLED_OPTIONAL_FEATURES = 286265094,
+  INITIAL_USER_INFO = 299896583,
+  SWITCH_USER = 299896584,
+  CREATE_USER = 299896585,
+  REMOVE_USER = 299896586,
+  USER_IDENTIFICATION_ASSOCIATION = 299896587,
+  EVS_SERVICE_REQUEST = 289476368,
+  POWER_POLICY_REQ = 286265121,
+  POWER_POLICY_GROUP_REQ = 286265122,
+  CURRENT_POWER_POLICY = 286265123,
+  WATCHDOG_ALIVE = 290459441,
+  WATCHDOG_TERMINATED_PROCESS = 299896626,
+  VHAL_HEARTBEAT = 290459443,
+  CLUSTER_SWITCH_UI = 289410868,
+  CLUSTER_DISPLAY_STATE = 289476405,
+  CLUSTER_REPORT_STATE = 299896630,
+  CLUSTER_REQUEST_DISPLAY = 289410871,
+  CLUSTER_NAVIGATION_STATE = 292556600,
+  ELECTRONIC_TOLL_COLLECTION_CARD_TYPE = 289410873,
+  ELECTRONIC_TOLL_COLLECTION_CARD_STATUS = 289410874,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyAccess.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyAccess.aidl
new file mode 100644
index 0000000..ec9587f
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyAccess.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehiclePropertyAccess {
+  NONE = 0,
+  READ = 1,
+  WRITE = 2,
+  READ_WRITE = 3,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.aidl
new file mode 100644
index 0000000..5455fdd
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehiclePropertyChangeMode {
+  STATIC = 0,
+  ON_CHANGE = 1,
+  CONTINUOUS = 2,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyGroup.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyGroup.aidl
new file mode 100644
index 0000000..0c049c4
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyGroup.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehiclePropertyGroup {
+  SYSTEM = 268435456,
+  VENDOR = 536870912,
+  MASK = -268435456,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl
new file mode 100644
index 0000000..6d0e041
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehiclePropertyStatus {
+  AVAILABLE = 0,
+  UNAVAILABLE = 1,
+  ERROR = 2,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyType.aidl
new file mode 100644
index 0000000..da6d2c2
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehiclePropertyType.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehiclePropertyType {
+  STRING = 1048576,
+  BOOLEAN = 2097152,
+  INT32 = 4194304,
+  INT32_VEC = 4259840,
+  INT64 = 5242880,
+  INT64_VEC = 5308416,
+  FLOAT = 6291456,
+  FLOAT_VEC = 6356992,
+  BYTES = 7340032,
+  MIXED = 14680064,
+  MASK = 16711680,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleSeatOccupancyState.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleSeatOccupancyState.aidl
new file mode 100644
index 0000000..3e870e8
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleSeatOccupancyState.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleSeatOccupancyState {
+  UNKNOWN = 0,
+  VACANT = 1,
+  OCCUPIED = 2,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleTurnSignal.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleTurnSignal.aidl
new file mode 100644
index 0000000..78c1795
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleTurnSignal.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleTurnSignal {
+  NONE = 0,
+  RIGHT = 1,
+  LEFT = 2,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleUnit.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleUnit.aidl
new file mode 100644
index 0000000..034dec5
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleUnit.aidl
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible 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.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleUnit {
+  SHOULD_NOT_USE = 0,
+  METER_PER_SEC = 1,
+  RPM = 2,
+  HERTZ = 3,
+  PERCENTILE = 16,
+  MILLIMETER = 32,
+  METER = 33,
+  KILOMETER = 35,
+  MILE = 36,
+  CELSIUS = 48,
+  FAHRENHEIT = 49,
+  KELVIN = 50,
+  MILLILITER = 64,
+  LITER = 65,
+  GALLON = 66,
+  US_GALLON = 66,
+  IMPERIAL_GALLON = 67,
+  NANO_SECS = 80,
+  SECS = 83,
+  YEAR = 89,
+  WATT_HOUR = 96,
+  MILLIAMPERE = 97,
+  MILLIVOLT = 98,
+  MILLIWATTS = 99,
+  AMPERE_HOURS = 100,
+  KILOWATT_HOUR = 101,
+  KILOPASCAL = 112,
+  PSI = 113,
+  BAR = 114,
+  DEGREES = 128,
+  MILES_PER_HOUR = 144,
+  KILOMETERS_PER_HOUR = 145,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleVendorPermission.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleVendorPermission.aidl
new file mode 100644
index 0000000..58524f3
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleVendorPermission.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleVendorPermission {
+  PERMISSION_DEFAULT = 0,
+  PERMISSION_SET_VENDOR_CATEGORY_WINDOW = 1,
+  PERMISSION_GET_VENDOR_CATEGORY_WINDOW = 2,
+  PERMISSION_SET_VENDOR_CATEGORY_DOOR = 3,
+  PERMISSION_GET_VENDOR_CATEGORY_DOOR = 4,
+  PERMISSION_SET_VENDOR_CATEGORY_SEAT = 5,
+  PERMISSION_GET_VENDOR_CATEGORY_SEAT = 6,
+  PERMISSION_SET_VENDOR_CATEGORY_MIRROR = 7,
+  PERMISSION_GET_VENDOR_CATEGORY_MIRROR = 8,
+  PERMISSION_SET_VENDOR_CATEGORY_INFO = 9,
+  PERMISSION_GET_VENDOR_CATEGORY_INFO = 10,
+  PERMISSION_SET_VENDOR_CATEGORY_ENGINE = 11,
+  PERMISSION_GET_VENDOR_CATEGORY_ENGINE = 12,
+  PERMISSION_SET_VENDOR_CATEGORY_HVAC = 13,
+  PERMISSION_GET_VENDOR_CATEGORY_HVAC = 14,
+  PERMISSION_SET_VENDOR_CATEGORY_LIGHT = 15,
+  PERMISSION_GET_VENDOR_CATEGORY_LIGHT = 16,
+  PERMISSION_SET_VENDOR_CATEGORY_1 = 65536,
+  PERMISSION_GET_VENDOR_CATEGORY_1 = 69632,
+  PERMISSION_SET_VENDOR_CATEGORY_2 = 131072,
+  PERMISSION_GET_VENDOR_CATEGORY_2 = 135168,
+  PERMISSION_SET_VENDOR_CATEGORY_3 = 196608,
+  PERMISSION_GET_VENDOR_CATEGORY_3 = 200704,
+  PERMISSION_SET_VENDOR_CATEGORY_4 = 262144,
+  PERMISSION_GET_VENDOR_CATEGORY_4 = 266240,
+  PERMISSION_SET_VENDOR_CATEGORY_5 = 327680,
+  PERMISSION_GET_VENDOR_CATEGORY_5 = 331776,
+  PERMISSION_SET_VENDOR_CATEGORY_6 = 393216,
+  PERMISSION_GET_VENDOR_CATEGORY_6 = 397312,
+  PERMISSION_SET_VENDOR_CATEGORY_7 = 458752,
+  PERMISSION_GET_VENDOR_CATEGORY_7 = 462848,
+  PERMISSION_SET_VENDOR_CATEGORY_8 = 524288,
+  PERMISSION_GET_VENDOR_CATEGORY_8 = 528384,
+  PERMISSION_SET_VENDOR_CATEGORY_9 = 589824,
+  PERMISSION_GET_VENDOR_CATEGORY_9 = 593920,
+  PERMISSION_SET_VENDOR_CATEGORY_10 = 655360,
+  PERMISSION_GET_VENDOR_CATEGORY_10 = 659456,
+  PERMISSION_NOT_ACCESSIBLE = -268435456,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsAvailabilityStateIntegerValuesIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsAvailabilityStateIntegerValuesIndex.aidl
new file mode 100644
index 0000000..0dcfbc4
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsAvailabilityStateIntegerValuesIndex.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VmsAvailabilityStateIntegerValuesIndex {
+  MESSAGE_TYPE = 0,
+  SEQUENCE_NUMBER = 1,
+  NUMBER_OF_ASSOCIATED_LAYERS = 2,
+  LAYERS_START = 3,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsBaseMessageIntegerValuesIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsBaseMessageIntegerValuesIndex.aidl
new file mode 100644
index 0000000..45514d0
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsBaseMessageIntegerValuesIndex.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VmsBaseMessageIntegerValuesIndex {
+  MESSAGE_TYPE = 0,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsMessageType.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsMessageType.aidl
new file mode 100644
index 0000000..1248c06
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsMessageType.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VmsMessageType {
+  SUBSCRIBE = 1,
+  SUBSCRIBE_TO_PUBLISHER = 2,
+  UNSUBSCRIBE = 3,
+  UNSUBSCRIBE_TO_PUBLISHER = 4,
+  OFFERING = 5,
+  AVAILABILITY_REQUEST = 6,
+  SUBSCRIPTIONS_REQUEST = 7,
+  AVAILABILITY_RESPONSE = 8,
+  AVAILABILITY_CHANGE = 9,
+  SUBSCRIPTIONS_RESPONSE = 10,
+  SUBSCRIPTIONS_CHANGE = 11,
+  DATA = 12,
+  PUBLISHER_ID_REQUEST = 13,
+  PUBLISHER_ID_RESPONSE = 14,
+  PUBLISHER_INFORMATION_REQUEST = 15,
+  PUBLISHER_INFORMATION_RESPONSE = 16,
+  START_SESSION = 17,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.aidl
new file mode 100644
index 0000000..8b0e3a5
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex {
+  MESSAGE_TYPE = 0,
+  LAYER_TYPE = 1,
+  LAYER_SUBTYPE = 2,
+  LAYER_VERSION = 3,
+  PUBLISHER_ID = 4,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsMessageWithLayerIntegerValuesIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsMessageWithLayerIntegerValuesIndex.aidl
new file mode 100644
index 0000000..65dd4ae
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsMessageWithLayerIntegerValuesIndex.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VmsMessageWithLayerIntegerValuesIndex {
+  MESSAGE_TYPE = 0,
+  LAYER_TYPE = 1,
+  LAYER_SUBTYPE = 2,
+  LAYER_VERSION = 3,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsOfferingMessageIntegerValuesIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsOfferingMessageIntegerValuesIndex.aidl
new file mode 100644
index 0000000..fc2a9c1
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsOfferingMessageIntegerValuesIndex.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VmsOfferingMessageIntegerValuesIndex {
+  MESSAGE_TYPE = 0,
+  PUBLISHER_ID = 1,
+  NUMBER_OF_OFFERS = 2,
+  OFFERING_START = 3,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsPublisherInformationIntegerValuesIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsPublisherInformationIntegerValuesIndex.aidl
new file mode 100644
index 0000000..a9b017f
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsPublisherInformationIntegerValuesIndex.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VmsPublisherInformationIntegerValuesIndex {
+  MESSAGE_TYPE = 0,
+  PUBLISHER_ID = 1,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsStartSessionMessageIntegerValuesIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsStartSessionMessageIntegerValuesIndex.aidl
new file mode 100644
index 0000000..d942bc8
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsStartSessionMessageIntegerValuesIndex.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VmsStartSessionMessageIntegerValuesIndex {
+  MESSAGE_TYPE = 0,
+  SERVICE_ID = 1,
+  CLIENT_ID = 2,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsSubscriptionsStateIntegerValuesIndex.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsSubscriptionsStateIntegerValuesIndex.aidl
new file mode 100644
index 0000000..796d7f7
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VmsSubscriptionsStateIntegerValuesIndex.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.vehicle;
+@Backing(type="int") @VintfStability
+enum VmsSubscriptionsStateIntegerValuesIndex {
+  MESSAGE_TYPE = 0,
+  SEQUENCE_NUMBER = 1,
+  NUMBER_OF_LAYERS = 2,
+  NUMBER_OF_ASSOCIATED_LAYERS = 3,
+  SUBSCRIPTIONS_START = 4,
+}
diff --git a/automotive/vehicle/aidl/aidl_test/AidlHidlCompatibilityTest.cpp b/automotive/vehicle/aidl/aidl_test/AidlHidlCompatibilityTest.cpp
new file mode 100644
index 0000000..f4f3f28
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_test/AidlHidlCompatibilityTest.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+
+#include <android/binder_enums.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+
+namespace hidl_vehicle = ::android::hardware::automotive::vehicle::V2_0;
+namespace aidl_vehicle = ::aidl::android::hardware::automotive::vehicle;
+using ::android::hardware::hidl_enum_range;
+using ::ndk::enum_range;
+
+TEST(AidlHidlCompatibilityTest, testHidlPropertiesDefinedInAidl) {
+    for (const auto prop : hidl_enum_range<hidl_vehicle::VehicleProperty>()) {
+        int propInt = ::android::hardware::automotive::vehicle::toInt(prop);
+        auto aidlProperties = enum_range<aidl_vehicle::VehicleProperty>();
+
+        ASSERT_NE(std::find(aidlProperties.begin(), aidlProperties.end(),
+                            static_cast<aidl_vehicle::VehicleProperty>(propInt)),
+                  aidlProperties.end())
+                << "property: " << propInt << " defined in HIDL, but not defined in AIDL";
+    }
+}
diff --git a/automotive/vehicle/aidl/aidl_test/Android.bp b/automotive/vehicle/aidl/aidl_test/Android.bp
new file mode 100644
index 0000000..5284a0a
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_test/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "VehicleHalAidlHidlCompatibilityTest",
+    srcs: ["*.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+        "libhidlbase",
+    ],
+    static_libs: [
+        "VehicleHalUtils",
+        "android.hardware.automotive.vehicle@2.0",
+        "libgtest",
+        "libgmock",
+    ],
+    defaults: ["VehicleHalDefaults"],
+    test_suites: ["device-tests"],
+    vendor: true,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserRequest.aidl
new file mode 100644
index 0000000..624e5a6
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserRequest.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserInfo;
+import android.hardware.automotive.vehicle.UsersInfo;
+
+/**
+ * Defines the format of a CREATE_USER property.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable CreateUserRequest {
+    /**
+     * Arbitrary id used to map the response to the request.
+     */
+    int requestId;
+    /**
+     * Basic information about Android user that was created.
+     */
+    UserInfo newUserInfo;
+    /**
+     * Name of the new Android user.
+     */
+    @utf8InCpp String newUserName;
+    /**
+     * Information about the current state of the Android system.
+     */
+    UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserResponse.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserResponse.aidl
new file mode 100644
index 0000000..29db442
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserResponse.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.CreateUserStatus;
+
+/**
+ * Defines the result of a CreateUserRequest.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable CreateUserResponse {
+    /**
+     * Id of the request being responded.
+     */
+    int requestId;
+    /**
+     * Status of the request.
+     */
+    CreateUserStatus status = CreateUserStatus.SUCCESS;
+    /**
+     * HAL-specific error message.
+     *
+     * This argument is optional, and when defined, it's passed "as-is" to the caller. It could be
+     * used to show custom error messages to the end user.
+     */
+    @utf8InCpp String errorMessage;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserStatus.aidl
new file mode 100644
index 0000000..5c8c5f0
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserStatus.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Status of the response to a CreateUserRequest.
+ */
+@VintfStability
+@Backing(type="int")
+enum CreateUserStatus {
+    /**
+     * The request succeeded (for example, HAL created a new internal user, or associated the
+     * Android user to an existing internal user).
+     */
+    SUCCESS = 1,
+    /**
+     * The request failed (and Android will remove the Android user).
+     */
+    FAILURE = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CustomInputType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CustomInputType.aidl
new file mode 100644
index 0000000..10dbfd0
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CustomInputType.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.automotive.vehicle;
+
+/**
+ * Input code values for HW_CUSTOM_INPUT.
+ */
+@VintfStability
+@Backing(type="int")
+enum CustomInputType {
+    /**
+     * Ten functions representing the custom input code to be defined and implemented by OEM
+     * partners.
+     *
+     * OEMs need to formally contact Android team if more than 10 functions are required.
+     */
+    CUSTOM_EVENT_F1 = 1001,
+    CUSTOM_EVENT_F2 = 1002,
+    CUSTOM_EVENT_F3 = 1003,
+    CUSTOM_EVENT_F4 = 1004,
+    CUSTOM_EVENT_F5 = 1005,
+    CUSTOM_EVENT_F6 = 1006,
+    CUSTOM_EVENT_F7 = 1007,
+    CUSTOM_EVENT_F8 = 1008,
+    CUSTOM_EVENT_F9 = 1009,
+    CUSTOM_EVENT_F10 = 1010,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.aidl
new file mode 100644
index 0000000..8b0c471
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.aidl
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * This enum provides the canonical mapping for sensor properties that have a floating-point value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ * While these values do not directly map to SAE J1979 PIDs, an equivalence is listed next
+ * to each one to aid implementors.
+ */
+@VintfStability
+@Backing(type="int")
+enum DiagnosticFloatSensorIndex {
+    CALCULATED_ENGINE_LOAD = 0,
+    /*
+     * PID 0x04
+     */
+    ENGINE_COOLANT_TEMPERATURE = 1,
+    /*
+     * PID 0x05
+     */
+    SHORT_TERM_FUEL_TRIM_BANK1 = 2,
+    /*
+     * PID 0x06
+     */
+    LONG_TERM_FUEL_TRIM_BANK1 = 3,
+    /*
+     * PID 0x07
+     */
+    SHORT_TERM_FUEL_TRIM_BANK2 = 4,
+    /*
+     * PID 0x08
+     */
+    LONG_TERM_FUEL_TRIM_BANK2 = 5,
+    /*
+     * PID 0x09
+     */
+    FUEL_PRESSURE = 6,
+    /*
+     * PID 0x0A
+     */
+    INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 7,
+    /*
+     * PID 0x0B
+     */
+    ENGINE_RPM = 8,
+    /*
+     * PID 0x0C
+     */
+    VEHICLE_SPEED = 9,
+    /*
+     * PID 0x0D
+     */
+    TIMING_ADVANCE = 10,
+    /*
+     * PID 0x0E
+     */
+    MAF_AIR_FLOW_RATE = 11,
+    /*
+     * PID 0x10
+     */
+    THROTTLE_POSITION = 12,
+    /*
+     * PID 0x11
+     */
+    OXYGEN_SENSOR1_VOLTAGE = 13,
+    /*
+     * PID 0x14
+     */
+    OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM = 14,
+    /*
+     * PID 0x14
+     */
+    OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO = 15,
+    /*
+     * PID 0x24
+     */
+    OXYGEN_SENSOR2_VOLTAGE = 16,
+    /*
+     * PID 0x15
+     */
+    OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM = 17,
+    /*
+     * PID 0x15
+     */
+    OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO = 18,
+    /*
+     * PID 0x25
+     */
+    OXYGEN_SENSOR3_VOLTAGE = 19,
+    /*
+     * PID 0x16
+     */
+    OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM = 20,
+    /*
+     * PID 0x16
+     */
+    OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO = 21,
+    /*
+     * PID 0x26
+     */
+    OXYGEN_SENSOR4_VOLTAGE = 22,
+    /*
+     * PID 0x17
+     */
+    OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM = 23,
+    /*
+     * PID 0x17
+     */
+    OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO = 24,
+    /*
+     * PID 0x27
+     */
+    OXYGEN_SENSOR5_VOLTAGE = 25,
+    /*
+     * PID 0x18
+     */
+    OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM = 26,
+    /*
+     * PID 0x18
+     */
+    OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO = 27,
+    /*
+     * PID 0x28
+     */
+    OXYGEN_SENSOR6_VOLTAGE = 28,
+    /*
+     * PID 0x19
+     */
+    OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM = 29,
+    /*
+     * PID 0x19
+     */
+    OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO = 30,
+    /*
+     * PID 0x29
+     */
+    OXYGEN_SENSOR7_VOLTAGE = 31,
+    /*
+     * PID 0x1A
+     */
+    OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM = 32,
+    /*
+     * PID 0x1A
+     */
+    OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO = 33,
+    /*
+     * PID 0x2A
+     */
+    OXYGEN_SENSOR8_VOLTAGE = 34,
+    /*
+     * PID 0x1B
+     */
+    OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM = 35,
+    /*
+     * PID 0x1B
+     */
+    OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO = 36,
+    /*
+     * PID 0x2B
+     */
+    FUEL_RAIL_PRESSURE = 37,
+    /*
+     * PID 0x22
+     */
+    FUEL_RAIL_GAUGE_PRESSURE = 38,
+    /*
+     * PID 0x23
+     */
+    COMMANDED_EXHAUST_GAS_RECIRCULATION = 39,
+    /*
+     * PID 0x2C
+     */
+    EXHAUST_GAS_RECIRCULATION_ERROR = 40,
+    /*
+     * PID 0x2D
+     */
+    COMMANDED_EVAPORATIVE_PURGE = 41,
+    /*
+     * PID 0x2E
+     */
+    FUEL_TANK_LEVEL_INPUT = 42,
+    /*
+     * PID 0x2F
+     */
+    EVAPORATION_SYSTEM_VAPOR_PRESSURE = 43,
+    /*
+     * PID 0x32
+     */
+    CATALYST_TEMPERATURE_BANK1_SENSOR1 = 44,
+    /*
+     * PID 0x3C
+     */
+    CATALYST_TEMPERATURE_BANK2_SENSOR1 = 45,
+    /*
+     * PID 0x3D
+     */
+    CATALYST_TEMPERATURE_BANK1_SENSOR2 = 46,
+    /*
+     * PID 0x3E
+     */
+    CATALYST_TEMPERATURE_BANK2_SENSOR2 = 47,
+    /*
+     * PID 0x3F
+     */
+    ABSOLUTE_LOAD_VALUE = 48,
+    /*
+     * PID 0x43
+     */
+    FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO = 49,
+    /*
+     * PID 0x44
+     */
+    RELATIVE_THROTTLE_POSITION = 50,
+    /*
+     * PID 0x45
+     */
+    ABSOLUTE_THROTTLE_POSITION_B = 51,
+    /*
+     * PID 0x47
+     */
+    ABSOLUTE_THROTTLE_POSITION_C = 52,
+    /*
+     * PID 0x48
+     */
+    ACCELERATOR_PEDAL_POSITION_D = 53,
+    /*
+     * PID 0x49
+     */
+    ACCELERATOR_PEDAL_POSITION_E = 54,
+    /*
+     * PID 0x4A
+     */
+    ACCELERATOR_PEDAL_POSITION_F = 55,
+    /*
+     * PID 0x4B
+     */
+    COMMANDED_THROTTLE_ACTUATOR = 56,
+    /*
+     * PID 0x4C
+     */
+    ETHANOL_FUEL_PERCENTAGE = 57,
+    /*
+     * PID 0x52
+     */
+    ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58,
+    /*
+     * PID 0x53
+     */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59,
+    /*
+     * PID 0x55
+     */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60,
+    /*
+     * PID 0x57
+     */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,
+    /*
+     * PID 0x55
+     */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62,
+    /*
+     * PID 0x57
+     */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63,
+    /*
+     * PID 0x56
+     */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64,
+    /*
+     * PID 0x58
+     */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 65,
+    /*
+     * PID 0x56
+     */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 66,
+    /*
+     * PID 0x58
+     */
+    RELATIVE_ACCELERATOR_PEDAL_POSITION = 67,
+    /*
+     * PID 0x5A
+     */
+    HYBRID_BATTERY_PACK_REMAINING_LIFE = 68,
+    /*
+     * PID 0x5B
+     */
+    FUEL_INJECTION_TIMING = 69,
+    /*
+     * PID 0x5D
+     */
+    ENGINE_FUEL_RATE = 70,
+    /*
+     * PID 0x5E
+     */
+    // LAST_SYSTEM_INDEX = ENGINE_FUEL_RATE,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.aidl
new file mode 100644
index 0000000..321b7ff
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.aidl
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * This enum provides the canonical mapping for sensor properties that have an integer value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Some of the properties are represented as an integer mapping to another enum. In those cases
+ * expect a comment by the property definition describing the enum to look at for the mapping.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ * While these values do not directly map to SAE J1979 PIDs, an equivalence is listed next
+ * to each one to aid implementors.
+ */
+@VintfStability
+@Backing(type="int")
+enum DiagnosticIntegerSensorIndex {
+    /**
+     * refer to FuelSystemStatus for a description of this value.
+     */
+    FUEL_SYSTEM_STATUS = 0,
+    /*
+     * PID 0x03
+     */
+    MALFUNCTION_INDICATOR_LIGHT_ON = 1,
+    /*
+     * PID 0x01
+     *
+     *
+     * refer to IgnitionMonitorKind for a description of this value.
+     */
+    IGNITION_MONITORS_SUPPORTED = 2,
+    /*
+     * PID 0x01
+     *
+     *
+     * The value of this sensor is a bitmask that specifies whether ignition-specific
+     * tests are available and whether they are complete. The semantics of the individual
+     * bits in this value are given by, respectively, SparkIgnitionMonitors and
+     * CompressionIgnitionMonitors depending on the value of IGNITION_MONITORS_SUPPORTED.
+     */
+    IGNITION_SPECIFIC_MONITORS = 3,
+    /*
+     * PID 0x01
+     */
+    INTAKE_AIR_TEMPERATURE = 4,
+    /*
+     * PID 0x0F
+     *
+     *
+     * refer to SecondaryAirStatus for a description of this value.
+     */
+    COMMANDED_SECONDARY_AIR_STATUS = 5,
+    /*
+     * PID 0x12
+     */
+    NUM_OXYGEN_SENSORS_PRESENT = 6,
+    /*
+     * PID 0x13
+     */
+    RUNTIME_SINCE_ENGINE_START = 7,
+    /*
+     * PID 0x1F
+     */
+    DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 8,
+    /*
+     * PID 0x21
+     */
+    WARMUPS_SINCE_CODES_CLEARED = 9,
+    /*
+     * PID 0x30
+     */
+    DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 10,
+    /*
+     * PID 0x31
+     */
+    ABSOLUTE_BAROMETRIC_PRESSURE = 11,
+    /*
+     * PID 0x33
+     */
+    CONTROL_MODULE_VOLTAGE = 12,
+    /*
+     * PID 0x42
+     */
+    AMBIENT_AIR_TEMPERATURE = 13,
+    /*
+     * PID 0x46
+     */
+    TIME_WITH_MALFUNCTION_LIGHT_ON = 14,
+    /*
+     * PID 0x4D
+     */
+    TIME_SINCE_TROUBLE_CODES_CLEARED = 15,
+    /*
+     * PID 0x4E
+     */
+    MAX_FUEL_AIR_EQUIVALENCE_RATIO = 16,
+    /*
+     * PID 0x4F
+     */
+    MAX_OXYGEN_SENSOR_VOLTAGE = 17,
+    /*
+     * PID 0x4F
+     */
+    MAX_OXYGEN_SENSOR_CURRENT = 18,
+    /*
+     * PID 0x4F
+     */
+    MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 19,
+    /*
+     * PID 0x4F
+     */
+    MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 20,
+    /*
+     * PID 0x50
+     *
+     *
+     * refer to FuelType for a description of this value.
+     */
+    FUEL_TYPE = 21,
+    /*
+     * PID 0x51
+     */
+    FUEL_RAIL_ABSOLUTE_PRESSURE = 22,
+    /*
+     * PID 0x59
+     */
+    ENGINE_OIL_TEMPERATURE = 23,
+    /*
+     * PID 0x5C
+     */
+    DRIVER_DEMAND_PERCENT_TORQUE = 24,
+    /*
+     * PID 0x61
+     */
+    ENGINE_ACTUAL_PERCENT_TORQUE = 25,
+    /*
+     * PID 0x62
+     */
+    ENGINE_REFERENCE_PERCENT_TORQUE = 26,
+    /*
+     * PID 0x63
+     */
+    ENGINE_PERCENT_TORQUE_DATA_IDLE = 27,
+    /*
+     * PID 0x64
+     */
+    ENGINE_PERCENT_TORQUE_DATA_POINT1 = 28,
+    /*
+     * PID 0x64
+     */
+    ENGINE_PERCENT_TORQUE_DATA_POINT2 = 29,
+    /*
+     * PID 0x64
+     */
+    ENGINE_PERCENT_TORQUE_DATA_POINT3 = 30,
+    /*
+     * PID 0x64
+     */
+    ENGINE_PERCENT_TORQUE_DATA_POINT4 = 31,
+    /*
+     * PID 0x64
+     */
+    // LAST_SYSTEM_INDEX = 31,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardStatus.aidl
new file mode 100644
index 0000000..94209ba
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardStatus.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by ELECTRONIC_TOLL_COLLECTION_CARD_STATUS.
+ */
+@VintfStability
+@Backing(type="int")
+enum ElectronicTollCollectionCardStatus {
+    UNKNOWN = 0,
+    ELECTRONIC_TOLL_COLLECTION_CARD_VALID = 1,
+    ELECTRONIC_TOLL_COLLECTION_CARD_INVALID = 2,
+    ELECTRONIC_TOLL_COLLECTION_CARD_NOT_INSERTED = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardType.aidl
new file mode 100644
index 0000000..46c5f48
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardType.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by ELECTRONIC_TOLL_COLLECTION_CARD_TYPE.
+ */
+@VintfStability
+@Backing(type="int")
+enum ElectronicTollCollectionCardType {
+    UNKNOWN = 0,
+    JP_ELECTRONIC_TOLL_COLLECTION_CARD = 1,
+    JP_ELECTRONIC_TOLL_COLLECTION_CARD_V2 = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvConnectorType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvConnectorType.aidl
new file mode 100644
index 0000000..6e77f53
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvConnectorType.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.automotive.vehicle;
+
+/**
+ * Used by INFO_EV_CONNECTOR_TYPE to enumerate the type of connectors
+ * available to charge the vehicle.
+ */
+@VintfStability
+@Backing(type="int")
+enum EvConnectorType {
+    /**
+     * Default type if the vehicle does not know or report the EV connector
+     * type.
+     */
+    UNKNOWN = 0,
+    IEC_TYPE_1_AC = 1,
+    IEC_TYPE_2_AC = 2,
+    IEC_TYPE_3_AC = 3,
+    IEC_TYPE_4_DC = 4,
+    IEC_TYPE_1_CCS_DC = 5,
+    IEC_TYPE_2_CCS_DC = 6,
+    TESLA_ROADSTER = 7,
+    TESLA_HPWC = 8,
+    TESLA_SUPERCHARGER = 9,
+    GBT_AC = 10,
+    GBT_DC = 11,
+    /**
+     * Connector type to use when no other types apply. Before using this
+     * value, work with Google to see if the EvConnectorType enum can be
+     * extended with an appropriate value.
+     */
+    OTHER = 101,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceRequestIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceRequestIndex.aidl
new file mode 100644
index 0000000..d27e032
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceRequestIndex.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Index in int32VAlues for VehicleProperty#EVS_SERVICE_REQUEST property.
+ */
+@VintfStability
+@Backing(type="int")
+enum EvsServiceRequestIndex {
+    TYPE = 0,
+    STATE = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceState.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceState.aidl
new file mode 100644
index 0000000..ee5cd2b
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceState.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by EVS_SERVICE_REQUEST to enumerate the service's state.
+ */
+@VintfStability
+@Backing(type="int")
+enum EvsServiceState {
+    OFF = 0,
+    ON = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceType.aidl
new file mode 100644
index 0000000..6c621f7
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceType.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by EVS_SERVICE_REQUEST to enumerate the service's type.
+ */
+@VintfStability
+@Backing(type="int")
+enum EvsServiceType {
+    REARVIEW = 0,
+    SURROUNDVIEW = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/FuelType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/FuelType.aidl
new file mode 100644
index 0000000..98b1fa5
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/FuelType.aidl
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by INFO_FUEL_TYPE to enumerate the type of fuels this vehicle uses.
+ * Consistent with projection protocol.
+ */
+@VintfStability
+@Backing(type="int")
+enum FuelType {
+    /**
+     * Fuel type to use if the HU does not know on which types of fuel the vehicle
+     * runs. The use of this value is generally discouraged outside of aftermarket units.
+     */
+    FUEL_TYPE_UNKNOWN = 0,
+    /**
+     * Unleaded gasoline
+     */
+    FUEL_TYPE_UNLEADED = 1,
+    /**
+     * Leaded gasoline
+     */
+    FUEL_TYPE_LEADED = 2,
+    /**
+     * Diesel #1
+     */
+    FUEL_TYPE_DIESEL_1 = 3,
+    /**
+     * Diesel #2
+     */
+    FUEL_TYPE_DIESEL_2 = 4,
+    /**
+     * Biodiesel
+     */
+    FUEL_TYPE_BIODIESEL = 5,
+    /**
+     * 85% ethanol/gasoline blend
+     */
+    FUEL_TYPE_E85 = 6,
+    /**
+     * Liquified petroleum gas
+     */
+    FUEL_TYPE_LPG = 7,
+    /**
+     * Compressed natural gas
+     */
+    FUEL_TYPE_CNG = 8,
+    /**
+     * Liquified natural gas
+     */
+    FUEL_TYPE_LNG = 9,
+    /**
+     * Electric
+     */
+    FUEL_TYPE_ELECTRIC = 10,
+    /**
+     * Hydrogen fuel cell
+     */
+    FUEL_TYPE_HYDROGEN = 11,
+    /**
+     * Fuel type to use when no other types apply. Before using this value, work with
+     * Google to see if the FuelType enum can be extended with an appropriate value.
+     */
+    FUEL_TYPE_OTHER = 12,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueRequest.aidl
new file mode 100644
index 0000000..e5b3929
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueRequest.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VehiclePropValue;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable GetValueRequest {
+    // A unique request ID. For every client, the request ID must start with 1
+    // and monotonically increase for every SetValueRequest. If it hits
+    // LONG_MAX (very unlikely), it must loop back to 0.
+    long requestId;
+    // The property to get, for most properties, only the property ID or area
+    // ID would be used to identify the property, but for some properties, other
+    // fields might be used.
+    VehiclePropValue prop;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueRequests.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueRequests.aidl
new file mode 100644
index 0000000..3bbb88c
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueRequests.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.GetValueRequest;
+import android.os.ParcelFileDescriptor;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable GetValueRequests {
+    // A list of GetValueRequest to get if they fit the binder memory
+    // limitation.
+    GetValueRequest[] payloads;
+    // Shared memory file to store requests if they exceed binder memory
+    // limitation. Created by client, readable only at VHAL during the call.
+    // Caller could close it after the call.
+    @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueResult.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueResult.aidl
new file mode 100644
index 0000000..24c5757
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueResult.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.StatusCode;
+import android.hardware.automotive.vehicle.VehiclePropValue;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable GetValueResult {
+    // The ID for the request this response is for.
+    long requestId;
+    // The status for the getValue operation. If this is not OK, the getValue
+    // fails and prop should be ignored.
+    StatusCode status = StatusCode.OK;
+    // Contains the property value if status is OK. Must be null if status is
+    // not OK.
+    @nullable VehiclePropValue prop;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueResults.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueResults.aidl
new file mode 100644
index 0000000..a8bfb2c
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/GetValueResults.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.GetValueResult;
+import android.os.ParcelFileDescriptor;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable GetValueResults {
+    // The list of responses if they fit the binder memory limitation.
+    GetValueResult[] payloads;
+    // Shared memory file to store responses if they exceed binder memory
+    // limitation. Created by VHAL, readable only for the client.
+    // The client must close it after reading.
+    @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl
new file mode 100644
index 0000000..a947963
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.vehicle;
+
+import android.hardware.automotive.vehicle.GetValueRequests;
+import android.hardware.automotive.vehicle.IVehicleCallback;
+import android.hardware.automotive.vehicle.SetValueRequests;
+import android.hardware.automotive.vehicle.SubscribeOptions;
+import android.hardware.automotive.vehicle.VehiclePropConfigs;
+
+// Vehicle HAL interface.
+@VintfStability
+interface IVehicle {
+    /* An invalid memory ID. */
+    const long INVALID_MEMORY_ID = 0;
+    /* Maximum number of shared memory files for every subscription client. */
+    const int MAX_SHARED_MEMORY_FILES_PER_CLIENT = 3;
+
+    /**
+     * Returns a list of all property configurations supported by this vehicle
+     * HAL.
+     *
+     * @return A parcelable object that either contains a list of configs if
+     *    they fit the binder memory limitation or a shared memory file that
+     *    contains the configs. Must be parsed using
+     *    {@code android-automotive-large-parcelable} library.
+     */
+    VehiclePropConfigs getAllPropConfigs();
+
+    /**
+     * Returns a list of property configurations for given properties.
+     *
+     * If one of the requested VehicleProperty wasn't found it must return
+     * {@link StatusCode#INVALID_ARG}, otherwise a list of vehicle property
+     * configurations with {@link StatusCode#OK}.
+     *
+     * @param props A list of property IDs to get configurations for.
+     * @return A parcelable object that either contains a list of configs if
+     *    they fit the binder memory limitation or a shared memory file that
+     *    contains the configs. Must be parsed using
+     *    {@code android-automotive-large-parcelable} library.
+     */
+    VehiclePropConfigs getPropConfigs(in int[] props);
+
+    /**
+     * Get vehicle property values asynchronously.
+     *
+     * The {@link IVehicleCallback#onGetValues} method will be called when
+     * values are fetched. The method might be called multiple times, and each
+     * time with a subset of properties that have been fetched. E.g., if you
+     * request properties [A, B, C], the callback might be called twice with
+     * [A, C] and with [B]. Caller should not expect any order for
+     * {@link IVehicleCallback#onGetValues}.
+     *
+     * If this method returns error, it means we fail to get all the properties.
+     * If this method returns OK, there are still chances we fail to get some
+     * properties, which are indicated by {@link GetValueResult#status}.
+     *
+     * For {@link VehiclePropertyChangeMode#STATIC} properties, this method must
+     * always return the same value.
+     * For {@link VehiclePropertyChangeMode#ON_CHANGE} properties, it must
+     * return the latest available value. For cachable properties, the value
+     * within cache would be returned without talking with the actual car bus.
+     *
+     * Some properties like {@code RADIO_PRESET} requires to pass additional
+     * data in {@link VehiclePropValue} object.
+     *
+     * If there is no data available yet, which can happen during initial stage,
+     * {@link GetValueResult#status} contains {@link StatusCode#TRY_AGAIN}.
+     *
+     * Caller must pass a unique RequestID for each request, if any of the
+     * given request ID is duplicate with one of the pending request ID, this
+     * function must return {@link StatusCode#INVALID_ARG}.
+     *
+     * To prevent confusion, duplicate properties (same property ID and same
+     * area ID) are not allowed in a single call. This function must return
+     * {@link StatusCode#INVALID_ARG} for duplicate properties.
+     *
+     * @param callback A callback interface, whose 'onGetValues' would be called
+     *    after the value is fetched. Caller should use
+     *    {@code android-automotive-large-parcelable} library to parse the
+     *    returned {@link GetValueResult} object.
+     * @param requests An object that contains either a list of requested
+     *    properties or a shared memory file that contains the properties. The
+     *    object must be parsed using helper libraries on sender and receiver.
+     */
+    void getValues(IVehicleCallback callback, in GetValueRequests requests);
+
+    /**
+     * Set vehicle property values.
+     *
+     * The {@link IVehicleCallback#onSetValues} function would be called after
+     * the values set request are sent through vehicle bus or are failed to set.
+     * If the bus protocol supports confirmation, the callback would be called
+     * after getting the confirmation.
+     *
+     * For some vehicle bus such as CAN bus where confirmation is not supported,
+     * OnSetValues does not necessarily mean the value changes would be
+     * reflected in {@link #getValues} immediately.
+     *
+     * If the output status contains error, it means we fail to set all the
+     * properties. If we failed to set some of the values, they would be
+     * reflected as non OK {@link SetValueResult#status}.
+     *
+     * The order each property in the request is set is not guaranteed. If
+     * caller needs to make sure certain order in setting values, caller should
+     * set one value, wait for its callback and then set the other value.
+     *
+     * Timestamp of data must be ignored for set operation.
+     *
+     * Setting some properties requires having initial state available. If
+     * initial data is not available yet, the {@link SetValueResult#status}
+     * must be {@link StatusCode#TRY_AGAIN}. For a property with separate power
+     * control the {@link SetValueResult#status} must be
+     * {@link StatusCode#NOT_AVAILABLE} if property is not powered
+     * on.
+     *
+     * Caller must pass a unique RequestID for each request, if any of the
+     * given request ID is duplicate with one of the pending request ID, this
+     * function must return {@link StatusCode#INVALID_ARG}.
+     *
+     * To prevent confusion, duplicate properties (same property ID and same
+     * area ID) are not allowed in a single call. This function must return
+     * {@link StatusCode#INVALID_ARG} for duplicate properties.
+     *
+     * @param callback The callback, whose 'onSetValues' would be called after
+     *    set value request is sent to bus.
+     * @param requests An object that contains a list of {@link SetValueRequest}
+     *    or a shared memory file that stores the list of requests if they
+     *    exceed binder memory limitation, must be parsed using helper libraries
+     *    on sender and receiver.
+     */
+    void setValues(IVehicleCallback callback, in SetValueRequests requests);
+
+    /**
+     * Subscribes to property events.
+     *
+     * Clients must be able to subscribe to multiple properties at a time
+     * depending on data provided in options argument.
+     *
+     * For one callback, the is only one subscription for one property.
+     * A new subscription with a different sample rate would override the old
+     * subscription. One property could be subscribed multiple times for
+     * different callbacks.
+     *
+     * @param callback The subscription callbacks.
+     *    {@link IVehicleCallback#onPropertyEvent} would be called when a new
+     *    property event arrives.
+     *    {@link IVehicleCallback#onPropertySetError} would be called when a
+     *    property set request failed asynchronously. This is usually caused by
+     *    a property set failure message sent from the vehicle bus.
+     * @param options List of options to subscribe. SubscribeOption contains
+     *    information such as property Id, area Id, sample rate, etc.
+     * @param maxSharedMemoryFileCount The maximum number of shared memory files
+     *    allocated for in VHAL for this subscription. When a memory file is
+     *    handled back to the client, it cannot be used by VHAL to deliver
+     *    another event until the buffer is returned to VHAL by calling
+     *    returnSharedMemory. A larger maxSharedMemoryFileCount means a better
+     *    performance while handling large bursts of data, but also means larger
+     *    memory footprint. If you don't expect events arriving very frequently,
+     *    a recommended value is 2. A value of 0 means for each new property,
+     *    a new shared memory file would be created and no shared memory file
+     *    would ever be reused. This should only be configured for infrequent
+     *    events or devices with limited memory. This value must be >=0 and
+     *    < {@link MAX_SHARED_MEMORY_FILES_PER_CLIENT}.
+     */
+    void subscribe(in IVehicleCallback callback, in SubscribeOptions[] options,
+            int maxSharedMemoryFileCount);
+
+    /**
+     * Unsubscribes from property events.
+     *
+     * If 'callback' is not valid or 'propIds' were not subscribed for this
+     * 'callback', this method must return {@link StatusCode#INVALID_ARG}.
+     *
+     * @param callback The callback used in the previous subscription.
+     * @param propIds The IDs for the properties to unsubscribe.
+     */
+    void unsubscribe(in IVehicleCallback callback, in int[] propIds);
+
+    /**
+     * Return a shared memory file back to VHAL for recycle.
+     *
+     * This must be called after a shared memory file returned by
+     * {@link IVehicleCallback#onPropertyEvent} is no longer in-use by the
+     * client. This is usually called at the end of 'onPropertyEvent'.
+     *
+     * If the 'callback' is not valid or 'sharedMemoryId' does not match any
+     * SharedMemoryId in 'VehiclePropValues' passed to
+     * {@link IVehicleCallback#onPropertyEvent}, this method must return
+     * {@link StatusCode#INVALID_ARG}.
+     *
+     * @param callback The callback used in subscription.
+     * @param sharedMemoryId The ID returned by 'onPropertyEvent' representing
+     *    the used shared memory file to return.
+     */
+    void returnSharedMemory(in IVehicleCallback callback, long sharedMemoryId);
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl
new file mode 100644
index 0000000..2b50321
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.GetValueResults;
+import android.hardware.automotive.vehicle.SetValueResults;
+import android.hardware.automotive.vehicle.StatusCode;
+import android.hardware.automotive.vehicle.VehiclePropErrors;
+import android.hardware.automotive.vehicle.VehiclePropValues;
+
+@VintfStability
+interface IVehicleCallback {
+    /**
+     * Callback for {@link IVehicle#getValues} function.
+     *
+     * Called when some of the values to fetch are ready. This might be called
+     * once or multiple times for one 'getValues' request. Each callback
+     * contains part of the requested values. It is guaranteed that all the
+     * requested values would be returned in one of the callbacks, but the order
+     * each values are ready is not guaranteed.
+     *
+     * @param responses An object either contains a list of
+     *    {@link GetValueResult} if they fits the binder memory limitation or a
+     *    shared memory file that contains responses. Each
+     *    {@link GetValueResult} either contains the property value or contains
+     *    an error happened while getting the value.
+     *
+     *    {@link GetValueResult} also contains a requestId which indicates which
+     *    request this response is for. The responses object should be parsed by
+     *    {@code android-automotive-large-parcelable} library.
+     */
+    oneway void onGetValues(in GetValueResults responses);
+
+    /**
+     * Callback for {@link IVehicle#setValues} function.
+     *
+     * Called when VHAL have finished handling some of the property set request.
+     * This might be called once or multiple times for one 'setValues' requests.
+     * Each callback contains part of the requested values. It is guaranteed
+     * that all the set value statuses would be returned in one of the
+     * callbacks, but the order each values are set is not guaranteed.
+     *
+     * @param responses A list of {@link SetValueResult}. Each SetValueResult
+     *    contains a status indicating the status for setting the specific
+     *    property. The requestId indicates which request the response is for.
+     */
+    oneway void onSetValues(in SetValueResults responses);
+
+    /**
+     * Event callback happens whenever one or more variables that the API user
+     * has subscribed to need to be reported. This may be based purely on
+     * threshold and frequency (a regular subscription, see subscribe call's
+     * arguments) or when the {@link IVehicle#setValues} method was called and
+     * the actual change needs to be reported.
+     *
+     * @param propValues The updated property values wrapped in an object.
+     *    If the properties fit within binder limitation, they would be in
+     *    {@code propValues.payloads}, otherwise, they would be in a shared
+     *    memory file {@code propValues.sharedMemoryFd}.
+     *    The shared memory file is created by VHAL and must be returned to
+     *    VHAL using {@link IVehicle#returnSharedMemory} after use. There are
+     *    limited number of memory files created for each subscription, if
+     *    the client doesn't return the shared memory, the client might not get
+     *    event in the future.
+     * @param sharedMemoryFileCount Number of shared memory file allocated for
+     *    this subscription. This value could be used to tweak
+     *    {@code maxSharedMemoryFileCount} in {@link IVehicle#subscribe}. For
+     *    example, if you usually see sharedMemoryFileCount being the
+     *    maxSharedMemoryFileCount you set, this means you might need to
+     *    increase maxSharedMemoryFileCount.
+     */
+    oneway void onPropertyEvent(in VehiclePropValues propValues, int sharedMemoryFileCount);
+
+    /**
+     * Set property value is usually asynchronous operation. Thus even if
+     * client received {@link StatusCode#OK} from {@link IVehicle#setValues}, or
+     * received {@link StatusCode#OK} in {@link #onSetValues}, this doesn't
+     * guarantee that the value was successfully propagated to the vehicle
+     * network. If such rare event occurs this method must be called.
+     *
+     * @param errors A list of property set errors. If the VHAL implementation
+     *     does not batch the errors, this may only contain one error.
+     */
+    oneway void onPropertySetError(in VehiclePropErrors errors);
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequest.aidl
new file mode 100644
index 0000000..c7ba836
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequest.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.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.InitialUserInfoRequestType;
+import android.hardware.automotive.vehicle.UsersInfo;
+
+/**
+ * Defines the format of a INITIAL_USER_INFO request made by the Android system.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable InitialUserInfoRequest {
+    /**
+     * Arbitrary id used to map the HAL response to the request.
+     */
+    int requestId;
+    /**
+     * Type of request.
+     */
+    InitialUserInfoRequestType requestType = InitialUserInfoRequestType.UNKNOWN;
+    /**
+     * Information about the current state of the Android system.
+     */
+    UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequestType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequestType.aidl
new file mode 100644
index 0000000..829a63a
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequestType.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.automotive.vehicle;
+
+/**
+ * Defines when a INITIAL_USER_INFO request was made.
+ */
+@VintfStability
+@Backing(type="int")
+enum InitialUserInfoRequestType {
+    UNKNOWN = 0,
+    /**
+     * At the first time Android was booted (or after a factory reset).
+     */
+    FIRST_BOOT = 1,
+    /**
+     * At the first time Android was booted after the system was updated.
+     */
+    FIRST_BOOT_AFTER_OTA = 2,
+    /**
+     * When Android was booted "from scratch".
+     */
+    COLD_BOOT = 3,
+    /**
+     * When Android was resumed after the system was suspended to memory.
+     */
+    RESUME = 4,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponse.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponse.aidl
new file mode 100644
index 0000000..4c46fcb
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponse.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.InitialUserInfoResponseAction;
+import android.hardware.automotive.vehicle.UserInfo;
+
+/**
+ * Defines the format of a HAL response to a INITIAL_USER_INFO request.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable InitialUserInfoResponse {
+    /**
+     * Id of the request being responded.
+     */
+    int requestId;
+    /**
+     * which action the Android system should take.
+     */
+    InitialUserInfoResponseAction action = InitialUserInfoResponseAction.DEFAULT;
+    /**
+     * Information about the user that should be switched to or created.
+     */
+    UserInfo userToSwitchOrCreate;
+    /**
+     * System locales of the initial user (value will be passed as-is to
+     * android.provider.Settings.System.SYSTEM_LOCALES)
+     */
+    @utf8InCpp String userLocales;
+    /**
+     * Name of the user that should be created.
+     */
+    @utf8InCpp String userNameToCreate;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponseAction.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponseAction.aidl
new file mode 100644
index 0000000..9a0741e
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponseAction.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Defines which action the Android system should take in an INITIAL_USER_INFO request.
+ */
+@VintfStability
+@Backing(type="int")
+enum InitialUserInfoResponseAction {
+    /**
+     * Let the Android System decide what to do.
+     *
+     * For example, it might create a new user on first boot, and switch to the last
+     * active user afterwards.
+     */
+    DEFAULT = 0,
+    /**
+     * Switch to an existing Android user.
+     */
+    SWITCH = 1,
+    /**
+     * Create a new Android user (and switch to it).
+     */
+    CREATE = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.aidl
new file mode 100644
index 0000000..c1bba8e
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Ignition monitors common to both SPARK and COMPRESSION.
+ * These values come from the SAE J1979 standard.
+ */
+@VintfStability
+@Backing(type="int")
+enum Obd2CommonIgnitionMonitors {
+    COMPONENTS_AVAILABLE = 0x1 << 0,
+    COMPONENTS_INCOMPLETE = 0x1 << 1,
+    FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
+    FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
+    MISFIRE_AVAILABLE = 0x1 << 4,
+    MISFIRE_INCOMPLETE = 0x1 << 5,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CompressionIgnitionMonitors.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CompressionIgnitionMonitors.aidl
new file mode 100644
index 0000000..ccb49aa
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CompressionIgnitionMonitors.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.Obd2CommonIgnitionMonitors;
+
+/**
+ * Ignition monitors only available for COMPRESSION vehicles.
+ * These values come from the SAE J1979 standard.
+ */
+@VintfStability
+@Backing(type="int")
+enum Obd2CompressionIgnitionMonitors {
+    COMPONENTS_AVAILABLE = 0x1 << 0,
+    COMPONENTS_INCOMPLETE = 0x1 << 1,
+    FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
+    FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
+    MISFIRE_AVAILABLE = 0x1 << 4,
+    MISFIRE_INCOMPLETE = 0x1 << 5,
+    EGR_OR_VVT_AVAILABLE = 0x1 << 6,
+    EGR_OR_VVT_INCOMPLETE = 0x1 << 7,
+    PM_FILTER_AVAILABLE = 0x1 << 8,
+    PM_FILTER_INCOMPLETE = 0x1 << 9,
+    EXHAUST_GAS_SENSOR_AVAILABLE = 0x1 << 10,
+    EXHAUST_GAS_SENSOR_INCOMPLETE = 0x1 << 11,
+    BOOST_PRESSURE_AVAILABLE = 0x1 << 12,
+    BOOST_PRESSURE_INCOMPLETE = 0x1 << 13,
+    NOx_SCR_AVAILABLE = 0x1 << 14,
+    NOx_SCR_INCOMPLETE = 0x1 << 15,
+    NMHC_CATALYST_AVAILABLE = 0x1 << 16,
+    NMHC_CATALYST_INCOMPLETE = 0x1 << 17,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.aidl
new file mode 100644
index 0000000..8266ee2
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * The status of the vehicle's fuel system.
+ * These values come from the SAE J1979 standard.
+ */
+@VintfStability
+@Backing(type="int")
+enum Obd2FuelSystemStatus {
+    OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1,
+    CLOSED_LOOP = 2,
+    OPEN_ENGINE_LOAD_OR_DECELERATION = 4,
+    OPEN_SYSTEM_FAILURE = 8,
+    CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelType.aidl
new file mode 100644
index 0000000..c7b4f77
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelType.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * The fuel type(s) supported by a vehicle.
+ * These values come from the SAE J1979 standard.
+ */
+@VintfStability
+@Backing(type="int")
+enum Obd2FuelType {
+    NOT_AVAILABLE = 0,
+    GASOLINE = 1,
+    METHANOL = 2,
+    ETHANOL = 3,
+    DIESEL = 4,
+    LPG = 5,
+    CNG = 6,
+    PROPANE = 7,
+    ELECTRIC = 8,
+    BIFUEL_RUNNING_GASOLINE = 9,
+    BIFUEL_RUNNING_METHANOL = 10,
+    BIFUEL_RUNNING_ETHANOL = 11,
+    BIFUEL_RUNNING_LPG = 12,
+    BIFUEL_RUNNING_CNG = 13,
+    BIFUEL_RUNNING_PROPANE = 14,
+    BIFUEL_RUNNING_ELECTRIC = 15,
+    BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16,
+    HYBRID_GASOLINE = 17,
+    HYBRID_ETHANOL = 18,
+    HYBRID_DIESEL = 19,
+    HYBRID_ELECTRIC = 20,
+    HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21,
+    HYBRID_REGENERATIVE = 22,
+    BIFUEL_RUNNING_DIESEL = 23,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2IgnitionMonitorKind.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2IgnitionMonitorKind.aidl
new file mode 100644
index 0000000..7399f7b
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2IgnitionMonitorKind.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Defines which ignition monitors are available to be read.
+ */
+@VintfStability
+@Backing(type="int")
+enum Obd2IgnitionMonitorKind {
+    SPARK = 0,
+    COMPRESSION = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SecondaryAirStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SecondaryAirStatus.aidl
new file mode 100644
index 0000000..06748ca
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SecondaryAirStatus.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * The status of the vehicle's secondary air system.
+ * These values come from the SAE J1979 standard.
+ */
+@VintfStability
+@Backing(type="int")
+enum Obd2SecondaryAirStatus {
+    UPSTREAM = 1,
+    DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2,
+    FROM_OUTSIDE_OR_OFF = 4,
+    PUMP_ON_FOR_DIAGNOSTICS = 8,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SparkIgnitionMonitors.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SparkIgnitionMonitors.aidl
new file mode 100644
index 0000000..d814b5e
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SparkIgnitionMonitors.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.Obd2CommonIgnitionMonitors;
+
+/**
+ * Ignition monitors available for SPARK vehicles.
+ * These values come from the SAE J1979 standard.
+ */
+@VintfStability
+@Backing(type="int")
+enum Obd2SparkIgnitionMonitors {
+    COMPONENTS_AVAILABLE = 0x1 << 0,
+    COMPONENTS_INCOMPLETE = 0x1 << 1,
+    FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
+    FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
+    MISFIRE_AVAILABLE = 0x1 << 4,
+    MISFIRE_INCOMPLETE = 0x1 << 5,
+    EGR_AVAILABLE = 0x1 << 6,
+    EGR_INCOMPLETE = 0x1 << 7,
+    OXYGEN_SENSOR_HEATER_AVAILABLE = 0x1 << 8,
+    OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x1 << 9,
+    OXYGEN_SENSOR_AVAILABLE = 0x1 << 10,
+    OXYGEN_SENSOR_INCOMPLETE = 0x1 << 11,
+    AC_REFRIGERANT_AVAILABLE = 0x1 << 12,
+    AC_REFRIGERANT_INCOMPLETE = 0x1 << 13,
+    SECONDARY_AIR_SYSTEM_AVAILABLE = 0x1 << 14,
+    SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x1 << 15,
+    EVAPORATIVE_SYSTEM_AVAILABLE = 0x1 << 16,
+    EVAPORATIVE_SYSTEM_INCOMPLETE = 0x1 << 17,
+    HEATED_CATALYST_AVAILABLE = 0x1 << 18,
+    HEATED_CATALYST_INCOMPLETE = 0x1 << 19,
+    CATALYST_AVAILABLE = 0x1 << 20,
+    CATALYST_INCOMPLETE = 0x1 << 21,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/PortLocationType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/PortLocationType.aidl
new file mode 100644
index 0000000..ce26e1c
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/PortLocationType.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.automotive.vehicle;
+
+/**
+ * Used by INFO_FUEL_DOOR_LOCATION/INFO_CHARGE_PORT_LOCATION to enumerate fuel door or
+ * ev port location.
+ */
+@VintfStability
+@Backing(type="int")
+enum PortLocationType {
+    /**
+     * Default type if the vehicle does not know or report the Fuel door
+     * and ev port location.
+     */
+    UNKNOWN = 0,
+    FRONT_LEFT = 1,
+    FRONT_RIGHT = 2,
+    REAR_RIGHT = 3,
+    REAR_LEFT = 4,
+    FRONT = 5,
+    REAR = 6,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ProcessTerminationReason.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ProcessTerminationReason.aidl
new file mode 100644
index 0000000..4dec772
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ProcessTerminationReason.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * The reason why a process is terminated by car watchdog.
+ * This is used with WATCHDOG_TERMINATED_PROCESS property.
+ */
+@VintfStability
+@Backing(type="int")
+enum ProcessTerminationReason {
+    /**
+     * A process doesn't respond to car watchdog within the timeout.
+     */
+    NOT_RESPONDING = 1,
+    /**
+     * A process uses more IO operations than what is allowed.
+     */
+    IO_OVERUSE = 2,
+    /**
+     * A process uses more memory space than what is allowed.
+     */
+    MEMORY_OVERUSE = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RawPropValues.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RawPropValues.aidl
new file mode 100644
index 0000000..9c6875b
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RawPropValues.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.automotive.vehicle;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable RawPropValues {
+    /**
+     * This is used for properties of types VehiclePropertyType#INT
+     * and VehiclePropertyType#INT_VEC
+     */
+    int[] int32Values = {};
+
+    /**
+     * This is used for properties of types VehiclePropertyType#FLOAT
+     * and VehiclePropertyType#FLOAT_VEC
+     */
+    float[] floatValues;
+
+    /** This is used for properties of type VehiclePropertyType#INT64 */
+    long[] int64Values;
+
+    /** This is used for properties of type VehiclePropertyType#BYTES */
+    byte[] byteValues;
+
+    /** This is used for properties of type VehiclePropertyType#STRING */
+    @utf8InCpp String stringValue;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RemoveUserRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RemoveUserRequest.aidl
new file mode 100644
index 0000000..cb61da8
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RemoveUserRequest.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.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserInfo;
+import android.hardware.automotive.vehicle.UsersInfo;
+
+/**
+ * Defines the format of a REMOVE_USER property.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable RemoveUserRequest {
+    /**
+     * Arbitrary id used to map the response to the request.
+     */
+    int requestId;
+    /**
+     * Information about the Android user that was removed.
+     */
+    UserInfo removedUserInfo;
+    /**
+     * Information about the current state of the Android system.
+     */
+    UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RotaryInputType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RotaryInputType.aidl
new file mode 100644
index 0000000..5f08ed7
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RotaryInputType.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * A rotary control which can rotate without limits. These controls use HW_ROTARY_INPUT to report
+ * relative clockwise or counterclockwise motion. They have no absolute position.
+ */
+@VintfStability
+@Backing(type="int")
+enum RotaryInputType {
+    /**
+     * Main rotary control, typically in the center console, used to navigate the user interface.
+     */
+    ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION = 0,
+    /**
+     * Volume control for adjusting audio volume.
+     */
+    ROTARY_INPUT_TYPE_AUDIO_VOLUME = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueRequest.aidl
new file mode 100644
index 0000000..625f901
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueRequest.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VehiclePropValue;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable SetValueRequest {
+    // A unique request ID. For every client, the request ID must start with 1
+    // and monotonically increase for every SetValueRequest. If it hits
+    // LONG_MAX (very unlikely), it must loop back to 0.
+    long requestId;
+    // The value to set.
+    VehiclePropValue value;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueRequests.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueRequests.aidl
new file mode 100644
index 0000000..a690fa2
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueRequests.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.SetValueRequest;
+import android.os.ParcelFileDescriptor;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable SetValueRequests {
+    // The list of request if they fit the binder memory limitation.
+    SetValueRequest[] payloads;
+    // Shared memory file to store requests if they exceed binder memory
+    // limitation. Created by client, readable only at VHAL during the call.
+    // Caller could close it after the call.
+    @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueResult.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueResult.aidl
new file mode 100644
index 0000000..b3feeaa
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueResult.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.StatusCode;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable SetValueResult {
+    // The ID for the request this response is for.
+    long requestId;
+    // The status for the setValue operation.
+    StatusCode status = StatusCode.OK;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueResults.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueResults.aidl
new file mode 100644
index 0000000..9b0e505
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SetValueResults.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.SetValueResult;
+import android.os.ParcelFileDescriptor;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable SetValueResults {
+    // The list of responses if they fit the binder memory limitation.
+    SetValueResult[] payloads;
+    // Shared memory file to store responses if they exceed binder memory
+    // limitation. Created by VHAL, readable only for the client.
+    // The client must close it after reading.
+    @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl
new file mode 100644
index 0000000..23019ca
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.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.automotive.vehicle;
+
+/**
+ * Error codes used in vehicle HAL interface.
+ */
+@VintfStability
+@Backing(type="int")
+enum StatusCode {
+    OK = 0,
+    /**
+     * Try again.
+     */
+    TRY_AGAIN = 1,
+    /**
+     * Invalid argument provided.
+     */
+    INVALID_ARG = 2,
+    /**
+     * This code must be returned when device that associated with the vehicle
+     * property is not available. For example, when client tries to set HVAC
+     * temperature when the whole HVAC unit is turned OFF.
+     */
+    NOT_AVAILABLE = 3,
+    /**
+     * Access denied
+     */
+    ACCESS_DENIED = 4,
+    /**
+     * Something unexpected has happened in Vehicle HAL
+     */
+    INTERNAL_ERROR = 5,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeOptions.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeOptions.aidl
new file mode 100644
index 0000000..e68f7e3
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeOptions.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.automotive.vehicle;
+
+/**
+ * Encapsulates information about subscription to vehicle property events.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable SubscribeOptions {
+    /** Property to subscribe */
+    int propId;
+    /**
+     * Optional areas to subscribe for this property, if empty, would subscribe
+     * to all areas configured for this property.
+     */
+    int[] areaIds;
+    /**
+     * Sample rate in Hz.
+     *
+     * Must be provided for properties with
+     * VehiclePropertyChangeMode::CONTINUOUS. The value must be within
+     * VehiclePropConfig#minSamplingRate .. VehiclePropConfig#maxSamplingRate
+     * for a given property.
+     * This value indicates how many updates per second client wants to receive.
+     */
+    float sampleRate;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserMessageType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserMessageType.aidl
new file mode 100644
index 0000000..f6ace54
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserMessageType.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Defines the reason a SWITCH_USER call was made.
+ *
+ * The meaning of each constant is explained in that property.
+ */
+@VintfStability
+@Backing(type="int")
+enum SwitchUserMessageType {
+    UNKNOWN = 0,
+    LEGACY_ANDROID_SWITCH = 1,
+    ANDROID_SWITCH = 2,
+    VEHICLE_RESPONSE = 3,
+    VEHICLE_REQUEST = 4,
+    ANDROID_POST_SWITCH = 5,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserRequest.aidl
new file mode 100644
index 0000000..320632c
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserRequest.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.SwitchUserMessageType;
+import android.hardware.automotive.vehicle.UserInfo;
+import android.hardware.automotive.vehicle.UsersInfo;
+
+/**
+ * Defines the format of a SWITCH_USER property.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable SwitchUserRequest {
+    /**
+     * Arbitrary id used to map the response to the request.
+     */
+    int requestId;
+    /**
+     * Type of message.
+     */
+    SwitchUserMessageType messageType = SwitchUserMessageType.UNKNOWN;
+    /**
+     * Information about the Android user being switched to.
+     *
+     * Only the user id (but not the flags) should be set when the request is made by HAL.
+     */
+    UserInfo targetUser;
+    /**
+     * Information about the current state of the Android system.
+     *
+     * Should not be set when the request is made by HAL.
+     */
+    UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserResponse.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserResponse.aidl
new file mode 100644
index 0000000..106386d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserResponse.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.SwitchUserMessageType;
+import android.hardware.automotive.vehicle.SwitchUserStatus;
+
+/**
+ * Defines the result of a SwitchUserRequest.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable SwitchUserResponse {
+    /**
+     * Id of the request being responded.
+     */
+    int requestId;
+    /**
+     * Type of message.
+     */
+    SwitchUserMessageType messageType = SwitchUserMessageType.UNKNOWN;
+    /**
+     * Status of the request.
+     */
+    SwitchUserStatus status = SwitchUserStatus.SUCCESS;
+    /**
+     * HAL-specific error message.
+     *
+     * This argument is optional, and when defined, it's passed "as-is" to the caller. It could be
+     * used to show custom error messages to the end user.
+     */
+    @utf8InCpp String errorMessage;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserStatus.aidl
new file mode 100644
index 0000000..a84d1ce
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserStatus.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Status of the response to a SwitchUserRequest.
+ */
+@VintfStability
+@Backing(type="int")
+enum SwitchUserStatus {
+    /**
+     * The request succeeded and the HAL user was switched.
+     */
+    SUCCESS = 1,
+    /**
+     * The request failed and the HAL user remained the same.
+     */
+    FAILURE = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociation.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociation.aidl
new file mode 100644
index 0000000..4af5f72
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociation.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserIdentificationAssociationType;
+import android.hardware.automotive.vehicle.UserIdentificationAssociationValue;
+
+/**
+ * Helper struct used when getting a user/identification association type.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable UserIdentificationAssociation {
+    UserIdentificationAssociationType type = UserIdentificationAssociationType.INVALID;
+    UserIdentificationAssociationValue value = UserIdentificationAssociationValue.UNKNOWN;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationSetValue.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationSetValue.aidl
new file mode 100644
index 0000000..eceb30f
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationSetValue.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used to set a UserIdentificationAssociationType with an Android user.
+ */
+@VintfStability
+@Backing(type="int")
+enum UserIdentificationAssociationSetValue {
+    INVALID = 0,
+    /**
+     * Associate the identification type with the current foreground Android user.
+     */
+    ASSOCIATE_CURRENT_USER = 1,
+    /**
+     * Disassociate the identification type from the current foreground Android user.
+     */
+    DISASSOCIATE_CURRENT_USER = 2,
+    /**
+     * Disassociate the identification type from all Android users.
+     */
+    DISASSOCIATE_ALL_USERS = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationType.aidl
new file mode 100644
index 0000000..4b21b5a
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationType.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.automotive.vehicle;
+
+/**
+ * Types of mechanisms used to identify an Android user.
+ *
+ * See USER_IDENTIFICATION_ASSOCIATION for more details and example.
+ */
+@VintfStability
+@Backing(type="int")
+enum UserIdentificationAssociationType {
+    INVALID = 0,
+    /**
+     * Key used to unlock the car.
+     */
+    KEY_FOB = 1,
+    /**
+     * Custom mechanism defined by the OEM.
+     */
+    CUSTOM_1 = 101,
+    /**
+     * Custom mechanism defined by the OEM.
+     */
+    CUSTOM_2 = 102,
+    /**
+     * Custom mechanism defined by the OEM.
+     */
+    CUSTOM_3 = 103,
+    /**
+     * Custom mechanism defined by the OEM.
+     */
+    CUSTOM_4 = 104,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationValue.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationValue.aidl
new file mode 100644
index 0000000..28dad0d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationValue.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.automotive.vehicle;
+
+/**
+ * Whether a UserIdentificationAssociationType is associate with an Android user.
+ */
+@VintfStability
+@Backing(type="int")
+enum UserIdentificationAssociationValue {
+    /**
+     * Used when the status of an association could not be determined.
+     *
+     * For example, in a set() request, it would indicate a failure to set the given type.
+     */
+    UNKNOWN = 1,
+    /**
+     * The identification type is associated with the current foreground Android user.
+     */
+    ASSOCIATED_CURRENT_USER = 2,
+    /**
+     * The identification type is associated with another Android user.
+     */
+    ASSOCIATED_ANOTHER_USER = 3,
+    /**
+     * The identification type is not associated with any Android user.
+     */
+    NOT_ASSOCIATED_ANY_USER = 4,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationGetRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationGetRequest.aidl
new file mode 100644
index 0000000..82580d7
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationGetRequest.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserIdentificationAssociationType;
+import android.hardware.automotive.vehicle.UserInfo;
+
+/**
+ * Defines the format of a get() call to USER_IDENTIFICATION_ASSOCIATION.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable UserIdentificationGetRequest {
+    /**
+     * Id of the request being responded.
+     */
+    int requestId;
+    /**
+     * Information about the current foreground Android user.
+     */
+    UserInfo userInfo;
+    /**
+     * Number of association being queried.
+     */
+    int numberAssociationTypes;
+    /**
+     * Types of association being queried.
+     */
+    UserIdentificationAssociationType[] associationTypes;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationResponse.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationResponse.aidl
new file mode 100644
index 0000000..1487a70
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationResponse.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.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserIdentificationAssociation;
+
+/**
+ * Defines the result of a USER_IDENTIFICATION_ASSOCIATION - both for get() and set().
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable UserIdentificationResponse {
+    /**
+     * Id of the request being responded.
+     */
+    int requestId;
+    /**
+     * Number of associations being returned.
+     */
+    int numberAssociation;
+    /**
+     * Values associated with the user.
+     */
+    UserIdentificationAssociation[] associations;
+    /**
+     * HAL-specific error message.
+     *
+     * This argument is optional, and when defined, it's passed "as-is" to the caller. It could be
+     * used to show custom error messages to the end user.
+     */
+    @utf8InCpp String errorMessage;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetAssociation.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetAssociation.aidl
new file mode 100644
index 0000000..bfb9544
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetAssociation.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserIdentificationAssociationSetValue;
+import android.hardware.automotive.vehicle.UserIdentificationAssociationType;
+
+/**
+ * Helper struct used when setting a user/identification association type.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable UserIdentificationSetAssociation {
+    UserIdentificationAssociationType type = UserIdentificationAssociationType.INVALID;
+    UserIdentificationAssociationSetValue value = UserIdentificationAssociationSetValue.INVALID;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetRequest.aidl
new file mode 100644
index 0000000..223ff08
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetRequest.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserIdentificationSetAssociation;
+import android.hardware.automotive.vehicle.UserInfo;
+
+/**
+ * Defines the format of a set() call to USER_IDENTIFICATION_ASSOCIATION.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable UserIdentificationSetRequest {
+    /**
+     * Id of the request being responded.
+     */
+    int requestId;
+    /**
+     * Information about the current foreground Android user.
+     */
+    UserInfo userInfo;
+    /**
+     * Number of association being set.
+     */
+    int numberAssociations;
+    /**
+     * Associations being set.
+     */
+    UserIdentificationSetAssociation[] associations;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserInfo.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserInfo.aidl
new file mode 100644
index 0000000..20c72bd
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserInfo.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.automotive.vehicle;
+
+/**
+ * Information about a specific Android user.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable UserInfo {
+    /**
+     * System user.
+     *
+     * On automotive, that user is always running, although never on foreground (except during
+     * boot or exceptional circumstances).
+     */
+    const int USER_FLAG_SYSTEM = 0x01;
+    /**
+     * Guest users have restrictions.
+     */
+    const int USER_FLAG_GUEST = 0x02;
+    /**
+     * Ephemeral users have non-persistent state.
+     */
+    const int USER_FLAG_EPHEMERAL = 0x04;
+    /**
+     * Admin users have additional privileges such as permission to create other users.
+     */
+    const int USER_FLAG_ADMIN = 0x08;
+    /**
+     * Disabled users are marked for deletion.
+     */
+    const int USER_FLAG_DISABLED = 0x10;
+    /**
+     * Profile user is a profile of another user.
+     */
+    const int USER_FLAG_PROFILE = 0x20;
+    /*
+     * The user ID.
+     */
+    int userId = 0;
+    /*
+     * Bitmask for the user flags defined above (USER_FLAG_*).
+     */
+    int flags;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UsersInfo.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UsersInfo.aidl
new file mode 100644
index 0000000..ede36f7
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UsersInfo.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserInfo;
+
+/**
+ * Information about all Android users.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it's part of other structs, which
+ * in turn are converted to a VehiclePropValue.RawValue through libraries provided by the default
+ * Vehicle HAL implementation.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable UsersInfo {
+    /**
+     * The current foreground user.
+     */
+    UserInfo currentUser;
+    /**
+     * Number of existing users; includes the current user, recently removed users (with DISABLED
+     * flag), and profile users (with PROFILE flag).
+     */
+    int numberUsers;
+    /**
+     * List of existing users; includes the current user, recently removed users (with DISABLED
+     * flag), and profile users (with PROFILE flag).
+     */
+    UserInfo[] existingUsers;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateConfigFlag.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateConfigFlag.aidl
new file mode 100644
index 0000000..4d8e2f5
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateConfigFlag.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.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleApPowerStateConfigFlag {
+    /**
+     * AP can enter deep sleep state. If not set, AP will shutdown from
+     * VehicleApPowerState#SHUTDOWN_PREPARE power state when deep sleep is requested
+     * (via VehicleApPowerStateShutdownParam#CAN_SLEEP or
+     * VehicleApPowerStateShutdownParam#SLEEP_IMMEDIATELY flags)/
+     */
+    ENABLE_DEEP_SLEEP_FLAG = 0x1,
+    /**
+     * The power controller can power on AP from off state after timeout
+     * specified in VehicleApPowerSet VEHICLE_AP_POWER_SET_SHUTDOWN_READY message.
+     */
+    CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2,
+    /**
+     * AP can enter hibernation state. If not set, AP will shutdown from
+     * VehicleApPowerState#SHUTDOWN_PREPARE when hibernation is requested
+     * (via VehicleApPowerStateShutdownParam#CAN_HIBERNATE or
+     *  VehicleApPowerStateShutdownParam#HIBERNATE_IMMEDIATELY flags)
+     */
+    ENABLE_HIBERNATION_FLAG = 0x3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.aidl
new file mode 100644
index 0000000..e94fc76
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.aidl
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleApPowerStateReport {
+    /**
+     * The device has booted. CarService has initialized and is ready to accept commands
+     * from VHAL. The user is not logged in, and vendor apps and services are expected to
+     * control the display and audio.
+     * After reporting this state, AP will accept VehicleApPowerStateReq#ON or
+     * VehicleApPowerStateReq#SHUTDOWN_PREPARE. Other power state requests are ignored.
+     */
+    WAIT_FOR_VHAL = 0x1,
+    /**
+     * AP is ready to suspend.
+     * The AP will not send any more state reports after this.
+     * After reporting this state, AP will accept VehicleApPowerStateReq#FINISHED.
+     * Other power state requests are ignored.
+     *
+     * int32Values[1]: Time to turn AP back on, in seconds. Power controller should turn on
+     *                 AP after the specified time has elapsed, so AP can run tasks like
+     *                 update. If this value is 0, no wake up is requested. The power
+     *                 controller may not necessarily support timed wake-up.
+     */
+    DEEP_SLEEP_ENTRY = 0x2,
+    /**
+     * AP is exiting from deep sleep state.
+     * After reporting this state, AP will accept VehicleApPowerStateReq#ON or
+     * VehicleApPowerStateReq#SHUTDOWN_PREPARE. Other power state requests are ignored.
+     */
+    DEEP_SLEEP_EXIT = 0x3,
+    /**
+     * AP sends this message repeatedly while cleanup and idle tasks execute.
+     * After reporting this state, AP will accept VehicleApPowerStateReq#SHUTDOWN_PREPARE
+     * requesting immediate shutdown or VehicleApPowerStateReq#CANCEL_SHUTDOWN. Other
+     * power state requests are ignored.
+     *
+     * int32Values[1]: Time to postpone shutdown in ms. Maximum value is
+     *                 5000 ms.
+     *                 If AP needs more time, it will send another SHUTDOWN_POSTPONE
+     *                 message before the previous one expires.
+     */
+    SHUTDOWN_POSTPONE = 0x4,
+    /**
+     * AP is ready to shutdown.
+     * The AP will not send any more state reports after this.
+     * After reporting this state, AP will accept VehicleApPowerStateReq#FINISHED.
+     * Other power state requests are ignored.
+     *
+     * int32Values[1]: Time to turn AP back on, in seconds. Power controller should turn on
+     *                 AP after the specified time has elapsed so AP can run tasks like
+     *                 update. If this value is 0, no wake up is specified. The power
+     *                 controller may not necessarily support timed wake-up.
+     */
+    SHUTDOWN_START = 0x5,
+    /**
+     * AP is entering its normal operating state.
+     * After reporting this state, AP will accept VehicleApPowerStateReq#SHUTDOWN_PREPARE.
+     * Other power state requests are ignored.
+     */
+    ON = 0x6,
+    /**
+     * AP is preparing to shut down. In this state, Garage Mode is active and idle
+     * tasks are allowed to run.
+     * After reporting this state, AP will accept VehicleApPowerStateReq#SHUTDOWN_PREPARE
+     * requesting immediate shutdown or VehicleApPowerStateReq#CANCEL_SHUTDOWN. Other
+     * power state requests are ignored.
+     */
+    SHUTDOWN_PREPARE = 0x7,
+    /**
+     * AP has stopped preparing to shut down.
+     * After reporting this state, AP will accept VehicleApPowerStateReq#ON or
+     * VehicleApPowerStateReq#SHUTDOWN_PREPARE. Other power state requests are ignored.
+     */
+    SHUTDOWN_CANCELLED = 0x8,
+    /**
+     * AP is ready to hibernate.
+     * The AP will not send any more state reports after this.
+     * After reporting this state, AP will accept VehicleApPowerStateReq#FINISHED.
+     * Other power state requests are ignored.
+     *
+     * int32Values[1]: Time to turn AP back on, in seconds. Power controller should turn on
+     *                 AP after the specified time has elapsed, so AP can run tasks like
+     *                 update. If this value is 0, no wake up is requested. The power
+     *                 controller may not necessarily support timed wake-up.
+     */
+    HIBERNATION_ENTRY = 0x9,
+    /**
+     * AP is exiting from hibernation state.
+     * After reporting this state, AP will accept VehicleApPowerStateReq#ON or
+     * VehicleApPowerStateReq#SHUTDOWN_PREPARE. Other power state requests are ignored.
+     */
+    HIBERNATION_EXIT = 0xA,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl
new file mode 100644
index 0000000..1031ebb
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleApPowerStateReq {
+    /**
+     * This requests Android to enter its normal operating state.
+     * This may be sent after the AP has reported
+     * VehicleApPowerStateReport#DEEP_SLEEP_EXIT,
+     * VehicleApPowerStateReport#HIBERNATION_EXIT,
+     * VehicleApPowerStateReport#SHUTDOWN_CANCELLED, or
+     * VehicleApPowerStateReport#WAIT_FOR_VHAL.
+     */
+    ON = 0,
+    /**
+     * The power controller issues this request to shutdown the system.
+     * This may be sent after the AP has reported
+     * VehicleApPowerStateReport#DEEP_SLEEP_EXIT,
+     * VehicleApPowerStateReport#HIBERNATION_EXIT,
+     * VehicleApPowerStateReport#ON,
+     * VehicleApPowerStateReport#SHUTDOWN_CANCELLED,
+     * VehicleApPowerStateReport#SHUTDOWN_POSTPONE,
+     * VehicleApPowerStateReport#SHUTDOWN_PREPARE, or
+     * VehicleApPowerStateReport#WAIT_FOR_VHAL.
+     *
+     * int32Values[1] : One of VehicleApPowerStateShutdownParam.
+     *                  This parameter indicates if the AP should shut
+     *                  down fully or sleep. This parameter also
+     *                  indicates if the shutdown should be immediate
+     *                  or if it can be postponed. If the shutdown can
+     *                  be postponed, AP requests postponing by sending
+     *                  VehicleApPowerStateReport#SHUTDOWN_POSTPONE.
+     */
+    SHUTDOWN_PREPARE = 1,
+    /**
+     * Cancel the shutdown.
+     * This may be sent after the AP has reported
+     * VehicleApPowerStateReport#SHUTDOWN_POSTPONE or
+     * VehicleApPowerStateReport#SHUTDOWN_PREPARE.
+     * After receiving this request, the AP will report
+     * VehicleApPowerStateReport#WAIT_FOR_VHAL in preparation to going ON.
+     */
+    CANCEL_SHUTDOWN = 2,
+    /**
+     * Completes the shutdown process.
+     * This may be sent after the AP has reported
+     * VehicleApPowerStateReport#DEEP_SLEEP_ENTRY or
+     * VehicleApPowerStateReport#HIBERNATION_ENTRY or
+     * VehicleApPowerStateReport#SHUTDOWN_START. The AP will not report new
+     * state information after receiving this request.
+     */
+    FINISHED = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReqIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReqIndex.aidl
new file mode 100644
index 0000000..aa556b0
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReqIndex.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Index in int32Values for VehicleProperty#AP_POWER_STATE_REQ property.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleApPowerStateReqIndex {
+    STATE = 0,
+    ADDITIONAL = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl
new file mode 100644
index 0000000..a863d14
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.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.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleApPowerStateShutdownParam {
+    /**
+     * AP must shutdown immediately. Postponing is not allowed.
+     */
+    SHUTDOWN_IMMEDIATELY = 1,
+    /**
+     * AP can enter deep sleep instead of shutting down completely.
+     */
+    CAN_SLEEP = 2,
+    /**
+     * AP can only shutdown with postponing allowed.
+     */
+    SHUTDOWN_ONLY = 3,
+    /**
+     * AP may enter deep sleep, but must either sleep or shut down immediately.
+     * Postponing is not allowed.
+     */
+    SLEEP_IMMEDIATELY = 4,
+    /**
+     * AP must hibernate (suspend to disk) immediately. Postponing is not allowed.
+     * Depending on the actual implementation, it may shut down immediately
+     */
+    HIBERNATE_IMMEDIATELY = 5,
+    /**
+     * AP can enter hibernation (suspend to disk) instead of shutting down completely.
+     */
+    CAN_HIBERNATE = 6,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleArea.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleArea.aidl
new file mode 100644
index 0000000..dab0349
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleArea.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleArea {
+    GLOBAL = 0x01000000,
+    /** WINDOW maps to enum VehicleAreaWindow */
+    WINDOW = 0x03000000,
+    /** MIRROR maps to enum VehicleAreaMirror */
+    MIRROR = 0x04000000,
+    /** SEAT maps to enum VehicleAreaSeat */
+    SEAT = 0x05000000,
+    /** DOOR maps to enum VehicleAreaDoor */
+    DOOR = 0x06000000,
+    /** WHEEL maps to enum VehicleAreaWheel */
+    WHEEL = 0x07000000,
+
+    MASK = 0x0f000000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
new file mode 100644
index 0000000..b44996d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.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.automotive.vehicle;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable VehicleAreaConfig {
+    /**
+     * Area id is ignored for VehiclePropertyGroup:GLOBAL properties.
+     */
+    int areaId;
+
+    /**
+     * If the property has @data_enum, leave the range to zero.
+     *
+     * Range will be ignored in the following cases:
+     *    - The VehiclePropertyType is not INT32, INT64 or FLOAT.
+     *    - Both of min value and max value are zero.
+     */
+
+    int minInt32Value;
+    int maxInt32Value;
+
+    long minInt64Value;
+    long maxInt64Value;
+
+    float minFloatValue;
+    float maxFloatValue;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaDoor.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaDoor.aidl
new file mode 100644
index 0000000..b729b8b
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaDoor.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleAreaDoor {
+    ROW_1_LEFT = 0x00000001,
+    ROW_1_RIGHT = 0x00000004,
+    ROW_2_LEFT = 0x00000010,
+    ROW_2_RIGHT = 0x00000040,
+    ROW_3_LEFT = 0x00000100,
+    ROW_3_RIGHT = 0x00000400,
+    HOOD = 0x10000000,
+    REAR = 0x20000000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaMirror.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaMirror.aidl
new file mode 100644
index 0000000..e1fd03b
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaMirror.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleAreaMirror {
+    DRIVER_LEFT = 0x00000001,
+    DRIVER_RIGHT = 0x00000002,
+    DRIVER_CENTER = 0x00000004,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
new file mode 100644
index 0000000..89d50ea
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Various Seats in the car.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleAreaSeat {
+    ROW_1_LEFT = 0x0001,
+    ROW_1_CENTER = 0x0002,
+    ROW_1_RIGHT = 0x0004,
+    ROW_2_LEFT = 0x0010,
+    ROW_2_CENTER = 0x0020,
+    ROW_2_RIGHT = 0x0040,
+    ROW_3_LEFT = 0x0100,
+    ROW_3_CENTER = 0x0200,
+    ROW_3_RIGHT = 0x0400,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWheel.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWheel.aidl
new file mode 100644
index 0000000..89f73cb
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWheel.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleAreaWheel {
+    UNKNOWN = 0x0,
+    LEFT_FRONT = 0x1,
+    RIGHT_FRONT = 0x2,
+    LEFT_REAR = 0x4,
+    RIGHT_REAR = 0x8,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWindow.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWindow.aidl
new file mode 100644
index 0000000..e1e8e85
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWindow.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Various windshields/windows in the car.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleAreaWindow {
+    FRONT_WINDSHIELD = 0x00000001,
+    REAR_WINDSHIELD = 0x00000002,
+    ROW_1_LEFT = 0x00000010,
+    ROW_1_RIGHT = 0x00000040,
+    ROW_2_LEFT = 0x00000100,
+    ROW_2_RIGHT = 0x00000400,
+    ROW_3_LEFT = 0x00001000,
+    ROW_3_RIGHT = 0x00004000,
+    ROOF_TOP_1 = 0x00010000,
+    ROOF_TOP_2 = 0x00020000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleDisplay.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleDisplay.aidl
new file mode 100644
index 0000000..1759a90
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleDisplay.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleDisplay {
+    /**
+     * The primary Android display (for example, center console)
+     */
+    MAIN = 0,
+    INSTRUMENT_CLUSTER = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleGear.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleGear.aidl
new file mode 100644
index 0000000..40e492e
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleGear.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Various gears which can be selected by user and chosen in system.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleGear {
+    GEAR_UNKNOWN = 0x0000,
+    GEAR_NEUTRAL = 0x0001,
+    GEAR_REVERSE = 0x0002,
+    GEAR_PARK = 0x0004,
+    GEAR_DRIVE = 0x0008,
+    GEAR_1 = 0x0010,
+    GEAR_2 = 0x0020,
+    GEAR_3 = 0x0040,
+    GEAR_4 = 0x0080,
+    GEAR_5 = 0x0100,
+    GEAR_6 = 0x0200,
+    GEAR_7 = 0x0400,
+    GEAR_8 = 0x0800,
+    GEAR_9 = 0x1000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHvacFanDirection.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHvacFanDirection.aidl
new file mode 100644
index 0000000..fa5d711
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHvacFanDirection.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.automotive.vehicle;
+
+/**
+ * Bit flags for fan direction
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleHvacFanDirection {
+    UNKNOWN = 0x0,
+    FACE = 0x1,
+    FLOOR = 0x2,
+    /**
+     * FACE_AND_FLOOR = FACE | FLOOR
+     */
+    FACE_AND_FLOOR = 0x3,
+    DEFROST = 0x4,
+    /**
+     * DEFROST_AND_FLOOR = DEFROST | FLOOR
+     */
+    DEFROST_AND_FLOOR = 0x06,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.aidl
new file mode 100644
index 0000000..93e42a0
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleHwKeyInputAction {
+    /**
+     * Key down
+     */
+    ACTION_DOWN = 0,
+    /**
+     * Key up
+     */
+    ACTION_UP = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl
new file mode 100644
index 0000000..4de97f6
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleIgnitionState {
+    UNDEFINED = 0,
+    /**
+     * Steering wheel is locked
+     */
+    LOCK = 1,
+    /**
+     * Steering wheel is not locked, engine and all accessories are OFF. If
+     * car can be in LOCK and OFF state at the same time than HAL must report
+     * LOCK state.
+     */
+    OFF,
+    /**
+     * Typically in this state accessories become available (e.g. radio).
+     * Instrument cluster and engine are turned off
+     */
+    ACC,
+    /**
+     * Ignition is in state ON. Accessories and instrument cluster available,
+     * engine might be running or ready to be started.
+     */
+    ON,
+    /**
+     * Typically in this state engine is starting (cranking).
+     */
+    START,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightState.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightState.aidl
new file mode 100644
index 0000000..ede20b7
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightState.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by lights state properties to enumerate the current state of the lights.
+ *
+ * Most XXX_LIGHTS_STATE properties will only report ON and OFF states.  Only
+ * the HEADLIGHTS_STATE property will report DAYTIME_RUNNING.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleLightState {
+    OFF = 0,
+    ON = 1,
+    DAYTIME_RUNNING = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightSwitch.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightSwitch.aidl
new file mode 100644
index 0000000..247e731
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightSwitch.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by lights switch properties to enumerate user selected switch setting.
+ *
+ * XXX_LIGHTS_SWITCH properties report the switch settings that the user
+ * selects.  The switch setting may be decoupled from the state reported if the
+ * user selects AUTOMATIC.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleLightSwitch {
+    OFF = 0,
+    ON = 1,
+    /**
+     * Daytime running lights mode.  Most cars automatically use DRL but some
+     * cars allow the user to activate them manually.
+     */
+    DAYTIME_RUNNING = 2,
+    /**
+     * Allows the vehicle ECU to set the lights automatically
+     */
+    AUTOMATIC = 0x100,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleOilLevel.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleOilLevel.aidl
new file mode 100644
index 0000000..bf3c858
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleOilLevel.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleOilLevel {
+    /**
+     * Oil level values
+     */
+    CRITICALLY_LOW = 0,
+    LOW = 1,
+    NORMAL = 2,
+    HIGH = 3,
+    ERROR = 4,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfig.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfig.aidl
new file mode 100644
index 0000000..1b48f0b
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfig.aidl
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VehicleAreaConfig;
+import android.hardware.automotive.vehicle.VehiclePropertyAccess;
+import android.hardware.automotive.vehicle.VehiclePropertyChangeMode;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable VehiclePropConfig {
+    /** Property identifier */
+    int prop;
+
+    /**
+     * Defines if the property is read or write or both.
+     */
+    VehiclePropertyAccess access = VehiclePropertyAccess.NONE;
+
+    /**
+     * Defines the change mode of the property.
+     */
+    VehiclePropertyChangeMode changeMode = VehiclePropertyChangeMode.STATIC;
+
+    /**
+     * Contains per-area configuration.
+     */
+    VehicleAreaConfig[] areaConfigs;
+
+    /** Contains additional configuration parameters */
+    int[] configArray;
+
+    /**
+     * Some properties may require additional information passed over this
+     * string. Most properties do not need to set this.
+     */
+    @utf8InCpp String configString;
+
+    /**
+     * Min sample rate in Hz.
+     * Must be defined for VehiclePropertyChangeMode::CONTINUOUS
+     */
+    float minSampleRate;
+
+    /**
+     * Must be defined for VehiclePropertyChangeMode::CONTINUOUS
+     * Max sample rate in Hz.
+     */
+    float maxSampleRate;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfigs.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfigs.aidl
new file mode 100644
index 0000000..9c2d5f7
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfigs.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VehiclePropConfig;
+import android.os.ParcelFileDescriptor;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable VehiclePropConfigs {
+    // The list of vehicle property configs if they fit the binder memory
+    // limitation.
+    VehiclePropConfig[] payloads;
+    // Shared memory file to store configs if they exceed binder memory
+    // limitation. Created by VHAL, readable only at client. Client could keep
+    // the fd opened or keep the FD mapped to access configs.
+    @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropError.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropError.aidl
new file mode 100644
index 0000000..2c31c72
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropError.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.StatusCode;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable VehiclePropError {
+    // Property ID.
+    int propId;
+    // Area ID.
+    int areaId;
+    // The error associated with this property.
+    StatusCode errorCode = StatusCode.OK;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropErrors.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropErrors.aidl
new file mode 100644
index 0000000..10a164d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropErrors.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VehiclePropError;
+import android.os.ParcelFileDescriptor;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable VehiclePropErrors {
+    // List of property set errors if they fit binder memory limitation.
+    VehiclePropError[] payloads;
+    // Shared memory file to store payloads if they exceed binder memory
+    // limitation.
+    @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValue.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValue.aidl
new file mode 100644
index 0000000..289f270
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValue.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.RawPropValues;
+import android.hardware.automotive.vehicle.VehiclePropertyStatus;
+
+/**
+ * Encapsulates the property name and the associated value. It
+ * is used across various API calls to set values, get values or to register for
+ * events.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable VehiclePropValue {
+    /** Time is elapsed nanoseconds since boot */
+    long timestamp;
+
+    /**
+     * Area type(s) for non-global property it must be one of the value from
+     * VehicleArea* enums or 0 for global properties.
+     */
+    int areaId;
+
+    /** Property identifier */
+    int prop;
+
+    /** Status of the property */
+    VehiclePropertyStatus status = VehiclePropertyStatus.AVAILABLE;
+
+    RawPropValues value;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValues.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValues.aidl
new file mode 100644
index 0000000..df44fdb
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValues.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VehiclePropValue;
+import android.os.ParcelFileDescriptor;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable VehiclePropValues {
+    // The list of vehicle properties if they fit the binder memory limitation.
+    VehiclePropValue[] payloads;
+    // An unique ID associated with this sharedMemoryFd file.
+    // Must be INVALID_MEMORY_ID if shared memory file is not used. If shared
+    // memory file is used, This ID must be sent back to the server using
+    // returnSharedMemory after this object has been used.
+    long sharedMemoryId;
+    // Shared memory file to store props if they exceed binder memory
+    // limitation. Created by VHAL, readable only at client. Client must close
+    // it after use and call returnSharedMemory.
+    @nullable ParcelFileDescriptor sharedMemoryFd;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
new file mode 100644
index 0000000..fe2de8f
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -0,0 +1,2640 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.vehicle;
+
+import android.hardware.automotive.vehicle.VehiclePropertyType;
+/**
+ * Declares all vehicle properties. VehicleProperty has a bitwise structure.
+ * Each property must have:
+ *  - a unique id from range 0x0100 - 0xffff
+ *  - associated data type using VehiclePropertyType
+ *  - property group (VehiclePropertyGroup)
+ *  - vehicle area (VehicleArea)
+ *
+ * Vendors are allowed to extend this enum with their own properties. In this
+ * case they must use VehiclePropertyGroup:VENDOR flag when the property is
+ * declared.
+ *
+ * When a property's status field is not set to AVAILABLE:
+ *  - IVehicle#set may return StatusCode::NOT_AVAILABLE.
+ *  - IVehicle#get is not guaranteed to work.
+ *
+ * Properties set to values out of range must be ignored and no action taken
+ * in response to such ill formed requests.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleProperty {
+    /**
+     * Undefined property.
+     */
+    INVALID = 0x00000000,
+    /**
+     * VIN of vehicle
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_VIN = 0x0100 + 0x10000000 + 0x01000000
+            + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+    /**
+     * Manufacturer of vehicle
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_MAKE = 0x0101 + 0x10000000 + 0x01000000
+            + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+    /**
+     * Model of vehicle
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_MODEL = 0x0102 + 0x10000000 + 0x01000000
+            + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+    /**
+     * Model year of vehicle.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:YEAR
+     */
+    INFO_MODEL_YEAR = 0x0103 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Fuel capacity of the vehicle in milliliters
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:MILLILITER
+     */
+    INFO_FUEL_CAPACITY = 0x0104 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * List of fuels the vehicle may use
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @data_enum FuelType
+     */
+    INFO_FUEL_TYPE = 0x0105 + 0x10000000 + 0x01000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    /**
+     * Battery capacity of the vehicle, if EV or hybrid.  This is the nominal
+     * battery capacity when the vehicle is new.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:WH
+     */
+    INFO_EV_BATTERY_CAPACITY = 0x0106 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * List of connectors this EV may use
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @data_enum EvConnectorType
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_EV_CONNECTOR_TYPE = 0x0107 + 0x10000000 + 0x01000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    /**
+     * Fuel door location
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @data_enum PortLocationType
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_FUEL_DOOR_LOCATION = 0x0108 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * EV port location
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @data_enum PortLocationType
+     */
+    INFO_EV_PORT_LOCATION = 0x0109 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Driver's seat location
+     * VHAL implementations must ignore the areaId. Use VehicleArea:GLOBAL.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @data_enum VehicleAreaSeat
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_DRIVER_SEAT = 0x010A + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Exterior dimensions of vehicle.
+     *
+     *  int32Values[0] = height
+     *  int32Values[1] = length
+     *  int32Values[2] = width
+     *  int32Values[3] = width including mirrors
+     *  int32Values[4] = wheel base
+     *  int32Values[5] = track width front
+     *  int32Values[6] = track width rear
+     *  int32Values[7] = curb to curb turning radius
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:MILLIMETER
+     */
+    INFO_EXTERIOR_DIMENSIONS = 0x010B + 0x10000000 + 0x01000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    /**
+     * Multiple EV port locations
+     *
+     * Implement this property if the vehicle has multiple EV ports.
+     * Port locations are defined in PortLocationType.
+     * For example, a car has one port in front left and one port in rear left:
+     *   int32Values[0] = PortLocationType::FRONT_LEFT
+     *   int32Values[0] = PortLocationType::REAR_LEFT
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @data_enum PortLocationType
+     */
+    INFO_MULTI_EV_PORT_LOCATIONS = 0x010C + 0x10000000 + 0x01000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    /**
+     * Current odometer value of the vehicle
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:KILOMETER
+     */
+    PERF_ODOMETER = 0x0204 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Speed of the vehicle
+     *
+     * The value must be positive when the vehicle is moving forward and negative when
+     * the vehicle is moving backward. This value is independent of gear value
+     * (CURRENT_GEAR or GEAR_SELECTION), for example, if GEAR_SELECTION is GEAR_NEUTRAL,
+     * PERF_VEHICLE_SPEED is positive when the vehicle is moving forward, negative when moving
+     * backward, and zero when not moving.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:METER_PER_SEC
+     */
+    PERF_VEHICLE_SPEED = 0x0207 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Speed of the vehicle for displays
+     *
+     * Some cars display a slightly slower speed than the actual speed.  This is
+     * usually displayed on the speedometer.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:METER_PER_SEC
+     */
+    PERF_VEHICLE_SPEED_DISPLAY = 0x0208 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Front bicycle model steering angle for vehicle
+     *
+     * Angle is in degrees.  Left is negative.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:DEGREES
+     */
+    PERF_STEERING_ANGLE = 0x0209 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Rear bicycle model steering angle for vehicle
+     *
+     * Angle is in degrees.  Left is negative.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:DEGREES
+     */
+    PERF_REAR_STEERING_ANGLE = 0x0210 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Temperature of engine coolant
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:CELSIUS
+     */
+    ENGINE_COOLANT_TEMP = 0x0301 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Engine oil level
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleOilLevel
+     */
+    ENGINE_OIL_LEVEL = 0x0303 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Temperature of engine oil
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:CELSIUS
+     */
+    ENGINE_OIL_TEMP = 0x0304 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Engine rpm
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:RPM
+     */
+    ENGINE_RPM = 0x0305 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Reports wheel ticks
+     *
+     * The first element in the vector is a reset count.  A reset indicates
+     * previous tick counts are not comparable with this and future ones.  Some
+     * sort of discontinuity in tick counting has occurred.
+     *
+     * The next four elements represent ticks for individual wheels in the
+     * following order: front left, front right, rear right, rear left.  All
+     * tick counts are cumulative.  Tick counts increment when the vehicle
+     * moves forward, and decrement when vehicles moves in reverse.  The ticks
+     * should be reset to 0 when the vehicle is started by the user.
+     *
+     *  int64Values[0] = reset count
+     *  int64Values[1] = front left ticks
+     *  int64Values[2] = front right ticks
+     *  int64Values[3] = rear right ticks
+     *  int64Values[4] = rear left ticks
+     *
+     * configArray is used to indicate the micrometers-per-wheel-tick value and
+     * which wheels are supported.  configArray is set as follows:
+     *
+     *  configArray[0], bits [0:3] = supported wheels.  Uses enum Wheel.
+     *  configArray[1] = micrometers per front left wheel tick
+     *  configArray[2] = micrometers per front right wheel tick
+     *  configArray[3] = micrometers per rear right wheel tick
+     *  configArray[4] = micrometers per rear left wheel tick
+     *
+     * NOTE:  If a wheel is not supported, its value shall always be set to 0.
+     *
+     * VehiclePropValue.timestamp must be correctly filled in.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     */
+    WHEEL_TICK = 0x0306 + 0x10000000 + 0x01000000
+            + 0x00510000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64_VEC
+    /**
+     * Fuel remaining in the vehicle, in milliliters
+     *
+     * Value may not exceed INFO_FUEL_CAPACITY
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:MILLILITER
+     */
+    FUEL_LEVEL = 0x0307 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Fuel door open
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    FUEL_DOOR_OPEN = 0x0308 + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * EV battery level in WH, if EV or hybrid
+     *
+     * Value may not exceed INFO_EV_BATTERY_CAPACITY
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:WH
+     */
+    EV_BATTERY_LEVEL = 0x0309 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * EV charge port open
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    EV_CHARGE_PORT_OPEN = 0x030A + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * EV charge port connected
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    EV_CHARGE_PORT_CONNECTED = 0x030B + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * EV instantaneous charge rate in milliwatts
+     *
+     * Positive value indicates battery is being charged.
+     * Negative value indicates battery being discharged.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:MW
+     */
+    EV_BATTERY_INSTANTANEOUS_CHARGE_RATE = 0x030C + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Range remaining
+     *
+     * Meters remaining of fuel and charge.  Range remaining shall account for
+     * all energy sources in a vehicle.  For example, a hybrid car's range will
+     * be the sum of the ranges based on fuel and battery.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @unit VehicleUnit:METER
+     */
+    RANGE_REMAINING = 0x0308 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Tire pressure
+     *
+     * Each tires is identified by its areaConfig.areaId config and their
+     * minFloatValue/maxFloatValue are used to store OEM recommended pressure
+     * range.
+     * The Min value in the areaConfig data represents the lower bound of
+     * the recommended tire pressure.
+     * The Max value in the areaConfig data represents the upper bound of
+     * the recommended tire pressure.
+     * For example:
+     * The following areaConfig indicates the recommended tire pressure
+     * of left_front tire is from 200.0 KILOPASCAL to 240.0 KILOPASCAL.
+     * .areaConfigs = {
+     *      VehicleAreaConfig {
+     *          .areaId = VehicleAreaWheel::LEFT_FRONT,
+     *          .minFloatValue = 200.0,
+     *          .maxFloatValue = 240.0,
+     *      }
+     * },
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:KILOPASCAL
+     */
+    TIRE_PRESSURE = 0x0309 + 0x10000000 + 0x07000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WHEEL,VehiclePropertyType:FLOAT
+    /**
+     * Critically low tire pressure
+     *
+     * This property indicates the critically low pressure threshold for each tire.
+     * It indicates when it is time for tires to be replaced or fixed. The value
+     * must be less than or equal to minFloatValue in TIRE_PRESSURE.
+     * Minimum and maximum property values (that is, minFloatValue, maxFloatValue)
+     * are not applicable to this property.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:KILOPASCAL
+     */
+    CRITICALLY_LOW_TIRE_PRESSURE = 0x030A + 0x10000000 + 0x07000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WHEEL,VehiclePropertyType:FLOAT
+    /**
+     * Currently selected gear
+     *
+     * This is the gear selected by the user.
+     *
+     * Values in the config data must represent the list of supported gears
+     * for this vehicle.  For example, config data for an automatic transmission
+     * must contain {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_DRIVE,
+     * GEAR_1, GEAR_2,...} and for manual transmission the list must be
+     * {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_1, GEAR_2,...}
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleGear
+     */
+    GEAR_SELECTION = 0x0400 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Current gear. In non-manual case, selected gear may not
+     * match the current gear. For example, if the selected gear is GEAR_DRIVE,
+     * the current gear will be one of GEAR_1, GEAR_2 etc, which reflects
+     * the actual gear the transmission is currently running in.
+     *
+     * Values in the config data must represent the list of supported gears
+     * for this vehicle.  For example, config data for an automatic transmission
+     * must contain {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_1, GEAR_2,...}
+     * and for manual transmission the list must be
+     * {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_1, GEAR_2,...}. This list need not be the
+     * same as that of the supported gears reported in GEAR_SELECTION.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleGear
+     */
+    CURRENT_GEAR = 0x0401 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Parking brake state.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    PARKING_BRAKE_ON = 0x0402 + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * Auto-apply parking brake.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    PARKING_BRAKE_AUTO_APPLY = 0x0403 + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * Warning for fuel low level.
+     *
+     * This property corresponds to the low fuel warning on the dashboard.
+     * Once FUEL_LEVEL_LOW is set, it should not be cleared until more fuel is
+     * added to the vehicle.  This property may take into account all fuel
+     * sources for a vehicle - for example:
+     *
+     *   For a gas powered vehicle, this property is based soley on gas level.
+     *   For a battery powered vehicle, this property is based solely on battery level.
+     *   For a hybrid vehicle, this property may be based on the combination of gas and battery
+     *      levels, at the OEM's discretion.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    FUEL_LEVEL_LOW = 0x0405 + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * Night mode
+     *
+     * True indicates that the night mode sensor has detected that the car cabin environment has
+     * low light. The platform could use this, for example, to enable appropriate UI for
+     * better viewing in dark or low light environments.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    NIGHT_MODE = 0x0407 + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * State of the vehicles turn signals
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleTurnSignal
+     */
+    TURN_SIGNAL_STATE = 0x0408 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Represents ignition state
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleIgnitionState
+     */
+    IGNITION_STATE = 0x0409 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * ABS is active
+     *
+     * Set to true when ABS is active.  Reset to false when ABS is off.  This
+     * property may be intermittently set (pulsing) based on the real-time
+     * state of the ABS system.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    ABS_ACTIVE = 0x040A + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * Traction Control is active
+     *
+     * Set to true when traction control (TC) is active.  Reset to false when
+     * TC is off.  This property may be intermittently set (pulsing) based on
+     * the real-time state of the TC system.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    TRACTION_CONTROL_ACTIVE = 0x040B + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /*
+     * HVAC Properties
+     *
+     * Additional rules for mapping a zoned HVAC property (except
+     * HVAC_MAX_DEFROST_ON) to AreaIDs:
+     *  - Every seat in VehicleAreaSeat that is available in the car, must be
+     *    part of an AreaID in the AreaID array.
+     *
+     * Example 1: A car has two front seats (ROW_1_LEFT, ROW_1_RIGHT) and three
+     *  back seats (ROW_2_LEFT, ROW_2_CENTER, ROW_2_RIGHT). There are two
+     *  temperature control units -- driver side and passenger side.
+     *   - A valid mapping set of AreaIDs for HVAC_TEMPERATURE_SET would be a
+     *     two element array:
+     *      - ROW_1_LEFT  | ROW_2_LEFT
+     *      - ROW_1_RIGHT | ROW_2_CENTER | ROW_2_RIGHT
+     *   - An alternative mapping for the same hardware configuration would be:
+     *      - ROW_1_LEFT  | ROW_2_CENTER | ROW_2_LEFT
+     *      - ROW_1_RIGHT | ROW_2_RIGHT
+     *  The temperature controllers are assigned to the seats which they
+     *  "most influence", but every seat must be included exactly once. The
+     *  assignment of the center rear seat to the left or right AreaID may seem
+     *  arbitrary, but the inclusion of every seat in exactly one AreaID ensures
+     *  that the seats in the car are all expressed and that a "reasonable" way
+     *  to affect each seat is available.
+     *
+     * Example 2: A car has three seat rows with two seats in the front row (ROW_1_LEFT,
+     *  ROW_1_RIGHT) and three seats in the second (ROW_2_LEFT, ROW_2_CENTER,
+     *  ROW_2_RIGHT) and third rows (ROW_3_LEFT, ROW_3_CENTER, ROW_3_RIGHT). There
+     *  are three temperature control units -- driver side, passenger side, and rear.
+     *   - A reasonable way to map HVAC_TEMPERATURE_SET to AreaIDs is a three
+     *     element array:
+     *     - ROW_1_LEFT
+     *     - ROW_1_RIGHT
+     *     - ROW_2_LEFT | ROW_2_CENTER | ROW_2_RIGHT | ROW_3_LEFT | ROW_3_CENTER | ROW_3_RIGHT
+     *
+     *
+     * Fan speed setting
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_FAN_SPEED = 0x0500 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Fan direction setting
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleHvacFanDirection
+     */
+    HVAC_FAN_DIRECTION = 0x0501 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * HVAC current temperature.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:CELSIUS
+     */
+    HVAC_TEMPERATURE_CURRENT = 0x0502 + 0x10000000 + 0x05000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:FLOAT
+    /**
+     * HVAC, target temperature set.
+     *
+     * The configArray is used to indicate the valid values for HVAC in Fahrenheit and Celsius.
+     * Android might use it in the HVAC app UI.
+     * The configArray is set as follows:
+     *      configArray[0] = [the lower bound of the supported temperature in Celsius] * 10.
+     *      configArray[1] = [the upper bound of the supported temperature in Celsius] * 10.
+     *      configArray[2] = [the increment in Celsius] * 10.
+     *      configArray[3] = [the lower bound of the supported temperature in Fahrenheit] * 10.
+     *      configArray[4] = [the upper bound of the supported temperature in Fahrenheit] * 10.
+     *      configArray[5] = [the increment in Fahrenheit] * 10.
+     * For example, if the vehicle supports temperature values as:
+     *      [16.0, 16.5, 17.0 ,..., 28.0] in Celsius
+     *      [60.5, 61.5, 62.5 ,..., 85.5] in Fahrenheit.
+     * The configArray should be configArray = {160, 280, 5, 605, 825, 10}.
+     *
+     * If the vehicle supports HVAC_TEMPERATURE_VALUE_SUGGESTION, the application can use
+     * that property to get the suggested value before setting HVAC_TEMPERATURE_SET. Otherwise,
+     * the application may choose the value in HVAC_TEMPERATURE_SET configArray by itself.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @unit VehicleUnit:CELSIUS
+     */
+    HVAC_TEMPERATURE_SET = 0x0503 + 0x10000000 + 0x05000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:FLOAT
+    /**
+     * Fan-based defrost for designated window.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_DEFROSTER = 0x0504 + 0x10000000 + 0x03000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
+    /**
+     * On/off AC for designated areaId
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @config_flags Supported areaIds
+     */
+    HVAC_AC_ON = 0x0505 + 0x10000000 + 0x05000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+    /**
+     * On/off max AC
+     *
+     * When MAX AC is on, the ECU may adjust the vent position, fan speed,
+     * temperature, etc as necessary to cool the vehicle as quickly as possible.
+     * Any parameters modified as a side effect of turning on/off the MAX AC
+     * parameter shall generate onPropertyEvent() callbacks to the VHAL.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_MAX_AC_ON = 0x0506 + 0x10000000 + 0x05000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+    /**
+     * On/off max defrost
+     *
+     * When MAX DEFROST is on, the ECU may adjust the vent position, fan speed,
+     * temperature, etc as necessary to defrost the windows as quickly as
+     * possible.  Any parameters modified as a side effect of turning on/off
+     * the MAX DEFROST parameter shall generate onPropertyEvent() callbacks to
+     * the VHAL.
+     * The AreaIDs for HVAC_MAX_DEFROST_ON indicate MAX DEFROST can be controlled
+     * in the area.
+     * For example:
+     * areaConfig.areaId = {ROW_1_LEFT | ROW_1_RIGHT} indicates HVAC_MAX_DEFROST_ON
+     * only can be controlled for the front rows.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_MAX_DEFROST_ON = 0x0507 + 0x10000000 + 0x05000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+    /**
+     * Recirculation on/off
+     *
+     * Controls the supply of exterior air to the cabin.  Recirc “on” means the
+     * majority of the airflow into the cabin is originating in the cabin.
+     * Recirc “off” means the majority of the airflow into the cabin is coming
+     * from outside the car.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_RECIRC_ON = 0x0508 + 0x10000000 + 0x05000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+    /**
+     * Enable temperature coupling between areas.
+     *
+     * The AreaIDs for HVAC_DUAL_ON property shall contain a combination of
+     * HVAC_TEMPERATURE_SET AreaIDs that can be coupled together. If
+     * HVAC_TEMPERATURE_SET is mapped to AreaIDs [a_1, a_2, ..., a_n], and if
+     * HVAC_DUAL_ON can be enabled to couple a_i and a_j, then HVAC_DUAL_ON
+     * property must be mapped to [a_i | a_j]. Further, if a_k and a_l can also
+     * be coupled together separately then HVAC_DUAL_ON must be mapped to
+     * [a_i | a_j, a_k | a_l].
+     *
+     * Example: A car has two front seats (ROW_1_LEFT, ROW_1_RIGHT) and three
+     *  back seats (ROW_2_LEFT, ROW_2_CENTER, ROW_2_RIGHT). There are two
+     *  temperature control units -- driver side and passenger side -- which can
+     *  be optionally synchronized. This may be expressed in the AreaIDs this way:
+     *  - HVAC_TEMPERATURE_SET->[ROW_1_LEFT | ROW_2_LEFT, ROW_1_RIGHT | ROW_2_CENTER | ROW_2_RIGHT]
+     *  - HVAC_DUAL_ON->[ROW_1_LEFT | ROW_2_LEFT | ROW_1_RIGHT | ROW_2_CENTER | ROW_2_RIGHT]
+     *
+     * When the property is enabled, the ECU must synchronize the temperature
+     * for the affected areas. Any parameters modified as a side effect
+     * of turning on/off the DUAL_ON parameter shall generate
+     * onPropertyEvent() callbacks to the VHAL. In addition, if setting
+     * a temperature (i.e. driver's temperature) changes another temperature
+     * (i.e. front passenger's temperature), then the appropriate
+     * onPropertyEvent() callbacks must be generated.  If a user changes a
+     * temperature that breaks the coupling (e.g. setting the passenger
+     * temperature independently) then the VHAL must send the appropriate
+     * onPropertyEvent() callbacks (i.e. HVAC_DUAL_ON = false,
+     * HVAC_TEMPERATURE_SET[AreaID] = xxx, etc).
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_DUAL_ON = 0x0509 + 0x10000000 + 0x05000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+    /**
+     * On/off automatic mode
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_AUTO_ON = 0x050A + 0x10000000 + 0x05000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+    /**
+     * Seat heating/cooling
+     *
+     * Negative values indicate cooling.
+     * 0 indicates off.
+     * Positive values indicate heating.
+     *
+     * Some vehicles may have multiple levels of heating and cooling. The
+     * min/max range defines the allowable range and number of steps in each
+     * direction.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_SEAT_TEMPERATURE = 0x050B + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Side Mirror Heat
+     *
+     * Increasing values denote higher heating levels for side mirrors.
+     * The Max value in the config data represents the highest heating level.
+     * The Min value in the config data MUST be zero and indicates no heating.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_SIDE_MIRROR_HEAT = 0x050C + 0x10000000 + 0x04000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
+    /**
+     * Steering Wheel Heating/Cooling
+     *
+     * Sets the amount of heating/cooling for the steering wheel
+     * config data Min and Max MUST be set appropriately.
+     * Positive value indicates heating.
+     * Negative value indicates cooling.
+     * 0 indicates temperature control is off.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_STEERING_WHEEL_HEAT = 0x050D + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Temperature units for display
+     *
+     * Indicates whether the vehicle is displaying temperature to the user as
+     * Celsius or Fahrenheit.
+     * VehiclePropConfig.configArray is used to indicate the supported temperature display units.
+     * For example: configArray[0] = CELSIUS
+     *              configArray[1] = FAHRENHEIT
+     *
+     * This parameter MAY be used for displaying any HVAC temperature in the system.
+     * Values must be one of VehicleUnit::CELSIUS or VehicleUnit::FAHRENHEIT
+     * Note that internally, all temperatures are represented in floating point Celsius.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleUnit
+     */
+    HVAC_TEMPERATURE_DISPLAY_UNITS = 0x050E + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Actual fan speed
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    HVAC_ACTUAL_FAN_SPEED_RPM = 0x050F + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Represents global power state for HVAC. Setting this property to false
+     * MAY mark some properties that control individual HVAC features/subsystems
+     * to UNAVAILABLE state. Setting this property to true MAY mark some
+     * properties that control individual HVAC features/subsystems to AVAILABLE
+     * state (unless any/all of them are UNAVAILABLE on their own individual
+     * merits).
+     *
+     * [Definition] HvacPower_DependentProperties: Properties that need HVAC to be
+     *   powered on in order to enable their functionality. For example, in some cars,
+     *   in order to turn on the AC, HVAC must be powered on first.
+     *
+     * HvacPower_DependentProperties list must be set in the
+     * VehiclePropConfig.configArray. HvacPower_DependentProperties must only contain
+     * properties that are associated with VehicleArea:SEAT. Properties that are not
+     * associated with VehicleArea:SEAT, for example, HVAC_DEFROSTER, must never
+     * depend on HVAC_POWER_ON property and must never be part of
+     * HvacPower_DependentProperties list.
+     *
+     * AreaID mapping for HVAC_POWER_ON property must contain all AreaIDs that
+     * HvacPower_DependentProperties are mapped to.
+     *
+     * Example 1: A car has two front seats (ROW_1_LEFT, ROW_1_RIGHT) and three back
+     *  seats (ROW_2_LEFT, ROW_2_CENTER, ROW_2_RIGHT). If the HVAC features (AC,
+     *  Temperature etc.) throughout the car are dependent on a single HVAC power
+     *  controller then HVAC_POWER_ON must be mapped to
+     *  [ROW_1_LEFT | ROW_1_RIGHT | ROW_2_LEFT | ROW_2_CENTER | ROW_2_RIGHT].
+     *
+     * Example 2: A car has two seats in the front row (ROW_1_LEFT, ROW_1_RIGHT) and
+     *   three seats in the second (ROW_2_LEFT, ROW_2_CENTER, ROW_2_RIGHT) and third
+     *   rows (ROW_3_LEFT, ROW_3_CENTER, ROW_3_RIGHT). If the car has temperature
+     *   controllers in the front row which can operate entirely independently of
+     *   temperature controllers in the back of the vehicle, then HVAC_POWER_ON
+     *   must be mapped to a two element array:
+     *   - ROW_1_LEFT | ROW_1_RIGHT
+     *   - ROW_2_LEFT | ROW_2_CENTER | ROW_2_RIGHT | ROW_3_LEFT | ROW_3_CENTER | ROW_3_RIGHT
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_POWER_ON = 0x0510 + 0x10000000 + 0x05000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+    /**
+     * Fan Positions Available
+     *
+     * This is a bit mask of fan positions available for the zone.  Each
+     * available fan direction is denoted by a separate entry in the vector.  A
+     * fan direction may have multiple bits from vehicle_hvac_fan_direction set.
+     * For instance, a typical car may have the following fan positions:
+     *   - FAN_DIRECTION_FACE (0x1)
+     *   - FAN_DIRECTION_FLOOR (0x2)
+     *   - FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR (0x3)
+     *   - FAN_DIRECTION_DEFROST (0x4)
+     *   - FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST (0x6)
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleHvacFanDirection
+     */
+    HVAC_FAN_DIRECTION_AVAILABLE = 0x0511 + 0x10000000 + 0x05000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32_VEC
+    /**
+     * Automatic recirculation on/off
+     *
+     * When automatic recirculation is ON, the HVAC system may automatically
+     * switch to recirculation mode if the vehicle detects poor incoming air
+     * quality.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_AUTO_RECIRC_ON = 0x0512 + 0x10000000 + 0x05000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+    /**
+     * Seat ventilation
+     *
+     * 0 indicates off.
+     * Positive values indicates ventilation level.
+     *
+     * Used by HVAC apps and Assistant to enable, change, or read state of seat
+     * ventilation.  This is different than seating cooling. It can be on at the
+     * same time as cooling, or not.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_SEAT_VENTILATION = 0x0513 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Electric defrosters' status
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_ELECTRIC_DEFROSTER_ON = 0x0514 + 0x10000000 + 0x03000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
+    /**
+     * Suggested values for setting HVAC temperature.
+     *
+     * Implement the property to help applications understand the closest supported temperature
+     * value in Celsius or Fahrenheit.
+     *
+     *      floatValues[0] = the requested value that an application wants to set a temperature to.
+     *      floatValues[1] = the unit for floatValues[0]. It should be one of
+     *                       {VehicleUnit:CELSIUS, VehicleUnit:FAHRENHEIT}.
+     *      floatValues[2] = the value OEMs suggested in CELSIUS. This value is not included
+     *                       in the request.
+     *      floatValues[3] = the value OEMs suggested in FAHRENHEIT. This value is not included
+     *                       in the request.
+     *
+     * An application calls set(VehiclePropValue propValue) with the requested value and unit for
+     * the value. OEMs need to return the suggested values in floatValues[2] and floatValues[3] by
+     * onPropertyEvent() callbacks.
+     *
+     * For example, when a user uses the voice assistant to set HVAC temperature to 66.2 in
+     * Fahrenheit.
+     * First, an application will set this property with the value
+     * [66.2, (float)VehicleUnit:FAHRENHEIT,0,0].
+     * If OEMs suggest to set 19.0 in Celsius or 66.5 in Fahrenheit for user's request, then VHAL
+     * must generate a callback with property value
+     * [66.2, (float)VehicleUnit:FAHRENHEIT, 19.0, 66.5]. After the voice assistant gets the
+     * callback, it will inform the user and set HVAC temperature to the suggested value.
+     *
+     * Another example, an application receives 21 Celsius as the current temperature value by
+     * querying HVC_TEMPERATURE_SET. But the application wants to know what value is displayed on
+     * the car's UI in Fahrenheit.
+     * For this, the application sets the property to [21, (float)VehicleUnit:CELSIUS, 0, 0]. If
+     * the suggested value by the OEM for 21 Celsius is 70 Fahrenheit, then VHAL must generate a
+     * callback with property value [21, (float)VehicleUnit:CELSIUS, 21.0, 70.0].
+     * In this case, the application can know that the value is 70.0 Fahrenheit in the car’s UI.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_TEMPERATURE_VALUE_SUGGESTION = 0x0515 + 0x10000000 + 0x01000000
+            + 0x00610000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT_VEC
+    /**
+     * Distance units for display
+     *
+     * Indicates which units the car is using to display distances to the user. Eg. Mile, Meter
+     * Kilometer.
+     *
+     * Distance units are defined in VehicleUnit.
+     * VehiclePropConfig.configArray is used to indicate the supported distance display units.
+     * For example: configArray[0] = METER
+     *              configArray[1] = KILOMETER
+     *              configArray[2] = MILE
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleUnit
+     */
+    DISTANCE_DISPLAY_UNITS = 0x0600 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Fuel volume units for display
+     *
+     * Indicates which units the car is using to display fuel volume to the user. Eg. Liter or
+     * Gallon.
+     *
+     * VehiclePropConfig.configArray is used to indicate the supported fuel volume display units.
+     * Volume units are defined in VehicleUnit.
+     * For example: configArray[0] = LITER
+     *              configArray[1] = GALLON
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleUnit
+     */
+    FUEL_VOLUME_DISPLAY_UNITS = 0x0601 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Tire pressure units for display
+     *
+     * Indicates which units the car is using to display tire pressure to the user. Eg. PSI, Bar or
+     * Kilopascal.
+     *
+     * VehiclePropConfig.configArray is used to indicate the supported pressure display units.
+     * Pressure units are defined in VehicleUnit.
+     * For example: configArray[0] = KILOPASCAL
+     *              configArray[1] = PSI
+     *              configArray[2] = BAR
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleUnit
+     */
+    TIRE_PRESSURE_DISPLAY_UNITS = 0x0602 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * EV battery units for display
+     *
+     * Indicates which units the car is using to display EV battery information to the user. Eg.
+     * watt-hours(Wh), kilowatt-hours(kWh) or ampere-hours(Ah).
+     *
+     * VehiclePropConfig.configArray is used to indicate the supported electrical energy units.
+     * Electrical energy units are defined in VehicleUnit.
+     * For example: configArray[0] = WATT_HOUR
+     *              configArray[1] = AMPERE_HOURS
+     *              configArray[2] = KILOWATT_HOUR
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleUnit
+     */
+    EV_BATTERY_DISPLAY_UNITS = 0x0603 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Fuel consumption units for display
+     *
+     * Indicates type of units the car is using to display fuel consumption information to user
+     * True indicates units are distance over volume such as MPG.
+     * False indicates units are volume over distance such as L/100KM.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME = 0x0604 + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * Speed units for display
+     *
+     * Indicates type of units the car is using to display speed to user. Eg. m/s, km/h, or mph.
+     *
+     * VehiclePropConfig.configArray is used to indicate the supported speed display units.
+     * Pressure units are defined in VehicleUnit.
+     * For example: configArray[0] = METER_PER_SEC
+     *              configArray[1] = MILES_PER_HOUR
+     *              configArray[2] = KILOMETERS_PER_HOUR
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    VEHICLE_SPEED_DISPLAY_UNITS = 0x0605 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Current date and time suggestion for the Car, encoded as Epoch time
+     * (in milliseconds). This value denotes the number of milliseconds seconds
+     * that have elapsed since 1/1/1970 UTC.
+     *
+     * This property signals a change in CarTime to Android. If the property is supported, VHAL
+     * must report the most accurate current CarTime when this property is read, and publish a
+     * change to this property when the CarTime value has changed. An on-change event for this
+     * property must be published when CarTime changes for any reason other than the natural elapse
+     * of time (time delta smaller than 500ms should not trigger an on change event). Android will
+     * read and subscribe to this property to fetch time from VHAL. This can be useful to
+     * synchronize Android's time with other vehicle systems (dash clock etc).
+     *     int64Values[0] = provided Epoch time (in milliseconds)
+     *
+     * Whenever a new Value for the property is received, AAOS will create
+     * and send an "ExternalTimeSuggestion" to the "TimeDetectorService".
+     * If other sources do not have a higher priority, Android will use this
+     * to set the system time. For information on how to adjust time source
+     * priorities and how time suggestions are handled (including how Android
+     * handles gitter, drift, and minimum resolution) see Time Detector Service
+     * documentation.
+     *
+     * Note that the property may take >0 ms to get propagated through the stack
+     * and, having a timestamped property helps reduce any time drift. So,
+     * for all reads to the property, the timestamp can be used to negate this
+     * drift:
+     *     drift = elapsedTime - PropValue.timestamp
+     *     effectiveTime = PropValue.value.int64Values[0] + drift
+     *
+     * It is strongly recommended that this property must not be used to retrieve
+     * time from ECUs using protocols (GNSS, NTP, Telephony etc). Since these
+     * protocols are already supported by Android, it is recommended to use
+     * Android’s own systems for them instead of wiring those through the VHAL
+     * using this property.
+     *
+     * WARNING: The value available through this property should not be dependent
+     * on value written by Android to ANDROID_EPOCH_TIME property in any way.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_ONLY
+     * @unit VehicleUnit:MILLI_SECS
+     */
+    EXTERNAL_CAR_TIME = 0x0608 + 0x10000000 // VehiclePropertyGroup:SYSTEM
+            + 0x01000000 // VehicleArea:GLOBAL
+            + 0x00500000, // VehiclePropertyType:INT64
+    /**
+     * Current date and time, encoded as Epoch time (in milliseconds).
+     * This value denotes the number of milliseconds seconds that have
+     * elapsed since 1/1/1970 UTC.
+     *
+     * CarServices will write to this value to give VHAL the Android system's
+     * time, if the VHAL supports this property. This can be useful to
+     * synchronize other vehicle systems (dash clock etc) with Android's time.
+     *
+     * AAOS writes to this property once during boot, and
+     * will thereafter write only when some time-source changes are propagated.
+     * AAOS will fill in VehiclePropValue.timestamp correctly.
+     * Note that AAOS will not send updates for natural elapse of time.
+     *     int64Values[0] = provided Unix time (in milliseconds)
+     *
+     * Note that the property may take >0 ms to get propagated through the stack
+     * and, having a timestamped property helps reduce any time drift. So,
+     * for all writes to the property, the timestamp can be used to negate this
+     * drift:
+     *     drift = elapsedTime - PropValue.timestamp
+     *     effectiveTime = PropValue.value.int64Values[0] + drift
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE_ONLY
+     * @unit VehicleUnit:MILLI_SECS
+     */
+    ANDROID_EPOCH_TIME = 0x0606 + 0x10000000 + 0x01000000
+            + 0x00500000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64
+    /**
+     * External encryption binding seed.
+     *
+     * This value is mixed with the local key storage encryption key.
+     * This property holds 16 bytes, and is expected to be persisted on an ECU separate from
+     * the IVI. The property is initially set by AAOS, who generates it using a CSRNG.
+     * AAOS will then read the property on subsequent boots. The binding seed is expected to be
+     * reliably persisted. Any loss of the seed results in a factory reset of the IVI.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    STORAGE_ENCRYPTION_BINDING_SEED = 0x0607 + 0x10000000 + 0x01000000
+            + 0x00700000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BYTES
+    /**
+     * Outside temperature
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:CELSIUS
+     */
+    ENV_OUTSIDE_TEMPERATURE = 0x0703 + 0x10000000 + 0x01000000
+            + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+    /**
+     * Property to control power state of application processor
+     *
+     * It is assumed that AP's power state is controlled by a separate power
+     * controller.
+     *
+     * For configuration information, VehiclePropConfig.configArray can have bit flag combining
+     * values in VehicleApPowerStateConfigFlag.
+     *
+     *   int32Values[0] : VehicleApPowerStateReq enum value
+     *   int32Values[1] : additional parameter relevant for each state,
+     *                    0 if not used.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    AP_POWER_STATE_REQ = 0x0A00 + 0x10000000 + 0x01000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    /**
+     * Property to report power state of application processor
+     *
+     * It is assumed that AP's power state is controller by separate power
+     * controller.
+     *
+     *   int32Values[0] : VehicleApPowerStateReport enum value
+     *   int32Values[1] : Time in ms to wake up, if necessary.  Otherwise 0.
+
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    AP_POWER_STATE_REPORT = 0x0A01 + 0x10000000 + 0x01000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    /**
+     * Property to report bootup reason for the current power on. This is a
+     * static property that will not change for the whole duration until power
+     * off. For example, even if user presses power on button after automatic
+     * power on with door unlock, bootup reason must stay with
+     * VehicleApPowerBootupReason#USER_UNLOCK.
+     *
+     * int32Values[0] must be VehicleApPowerBootupReason.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    AP_POWER_BOOTUP_REASON = 0x0A02 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Property to represent brightness of the display. Some cars have single
+     * control for the brightness of all displays and this property is to share
+     * change in that control.
+     *
+     * If this is writable, android side can set this value when user changes
+     * display brightness from Settings. If this is read only, user may still
+     * change display brightness from Settings, but that must not be reflected
+     * to other displays.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    DISPLAY_BRIGHTNESS = 0x0A03 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Property to feed H/W input events to android
+     *
+     * int32Values[0] : action defined by VehicleHwKeyInputAction
+     * int32Values[1] : key code, must use standard android key code
+     * int32Values[2] : target display defined in VehicleDisplay. Events not
+     *                  tied to specific display must be sent to
+     *                  VehicleDisplay#MAIN.
+     * int32Values[3] : [optional] Number of ticks. The value must be equal or
+     *                  greater than 1. When omitted, Android will default to 1.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @config_flags
+     */
+    HW_KEY_INPUT = 0x0A10 + 0x10000000 + 0x01000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    /**
+     * Property to feed H/W rotary events to android
+     *
+     * int32Values[0] : RotaryInputType identifying which rotary knob rotated
+     * int32Values[1] : number of detents (clicks), positive for clockwise,
+     *                  negative for counterclockwise
+     * int32Values[2] : target display defined in VehicleDisplay. Events not
+     *                  tied to specific display must be sent to
+     *                  VehicleDisplay#MAIN.
+     * int32values[3 .. 3 + abs(number of detents) - 2]:
+     *                  nanosecond deltas between pairs of consecutive detents,
+     *                  if the number of detents is > 1 or < -1
+     *
+     * VehiclePropValue.timestamp: when the rotation occurred. If the number of
+     *                             detents is > 1 or < -1, this is when the
+     *                             first detent of rotation occurred.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @data_enum RotaryInputType
+     * @access VehiclePropertyAccess:READ
+     */
+    HW_ROTARY_INPUT = 0x0A20 + 0x10000000 + 0x01000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    /**
+     * Defines a custom OEM partner input event.
+     *
+     * This input event must be used by OEM partners who wish to propagate events not supported
+     * by Android. It is composed by an array of int32 values only.
+     *
+     * The Android properties are:
+     *
+     * int32Values[0] : Input code identifying the function representing this event. Valid event
+     *                  types are defined by CustomInputType.CUSTOM_EVENT_F1 up to
+     *                  CustomInputType.CUSTOM_EVENT_F10. They represent the custom event to be
+     *                  defined by OEM partners.
+     * int32Values[1] : target display type defined in VehicleDisplay. Events not tied to specific
+     *                  display must be sent to VehicleDisplay#MAIN.
+     * int32Values[2] : repeat counter, if 0 then event is not repeated. Values 1 or above means
+     *                  how many times this event repeated.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @data_enum CustomInputType
+     * @access VehiclePropertyAccess:READ
+     */
+    HW_CUSTOM_INPUT = 0X0A30 + 0x10000000 + 0x01000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    /***************************************************************************
+     * Most Car Cabin properties have both a POSition and MOVE parameter.  These
+     * are used to control the various movements for seats, doors, and windows
+     * in a vehicle.
+     *
+     * A POS parameter allows the user to set the absolution position.  For
+     * instance, for a door, 0 indicates fully closed and max value indicates
+     * fully open.  Thus, a value halfway between min and max must indicate
+     * the door is halfway open.
+     *
+     * A MOVE parameter moves the device in a particular direction.  The sign
+     * indicates direction, and the magnitude indicates speed (if multiple
+     * speeds are available).  For a door, a move of -1 will close the door, and
+     * a move of +1 will open it.  Once a door reaches the limit of open/close,
+     * the door should automatically stop moving.  The user must NOT need to
+     * send a MOVE(0) command to stop the door at the end of its range.
+     **************************************************************************/
+
+    /**
+     * Door position
+     *
+     * This is an integer in case a door may be set to a particular position.
+     * Max value indicates fully open, min value (0) indicates fully closed.
+     *
+     * Some vehicles (minivans) can open the door electronically.  Hence, the
+     * ability to write this property.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    DOOR_POS = 0x0B00 + 0x10000000 + 0x06000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:INT32
+    /**
+     * Door move
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    DOOR_MOVE = 0x0B01 + 0x10000000 + 0x06000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:INT32
+    /**
+     * Door lock
+     *
+     * 'true' indicates door is locked
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    DOOR_LOCK = 0x0B02 + 0x10000000 + 0x06000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:BOOLEAN
+    /**
+     * Mirror Z Position
+     *
+     * Positive value indicates tilt upwards, negative value is downwards
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_Z_POS = 0x0B40 + 0x10000000 + 0x04000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
+    /**
+     * Mirror Z Move
+     *
+     * Positive value indicates tilt upwards, negative value is downwards
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_Z_MOVE = 0x0B41 + 0x10000000 + 0x04000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
+    /**
+     * Mirror Y Position
+     *
+     * Positive value indicate tilt right, negative value is left
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_Y_POS = 0x0B42 + 0x10000000 + 0x04000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
+    /**
+     * Mirror Y Move
+     *
+     * Positive value indicate tilt right, negative value is left
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_Y_MOVE = 0x0B43 + 0x10000000 + 0x04000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
+    /**
+     * Mirror Lock
+     *
+     * True indicates mirror positions are locked and not changeable
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_LOCK = 0x0B44 + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * Mirror Fold
+     *
+     * True indicates mirrors are folded
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_FOLD = 0x0B45 + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * Seat memory select
+     *
+     * This parameter selects the memory preset to use to select the seat
+     * position. The minValue is always 0, and the maxValue determines the
+     * number of seat positions available.
+     *
+     * For instance, if the driver's seat has 3 memory presets, the maxValue
+     * will be 3. When the user wants to select a preset, the desired preset
+     * number (1, 2, or 3) is set.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    SEAT_MEMORY_SELECT = 0x0B80 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat memory set
+     *
+     * This setting allows the user to save the current seat position settings
+     * into the selected preset slot.  The maxValue for each seat position
+     * must match the maxValue for SEAT_MEMORY_SELECT.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    SEAT_MEMORY_SET = 0x0B81 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seatbelt buckled
+     *
+     * True indicates belt is buckled.
+     *
+     * Write access indicates automatic seat buckling capabilities.  There are
+     * no known cars at this time, but you never know...
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BELT_BUCKLED = 0x0B82 + 0x10000000 + 0x05000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+    /**
+     * Seatbelt height position
+     *
+     * Adjusts the shoulder belt anchor point.
+     * Max value indicates highest position
+     * Min value indicates lowest position
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BELT_HEIGHT_POS = 0x0B83 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seatbelt height move
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BELT_HEIGHT_MOVE = 0x0B84 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat fore/aft position
+     *
+     * Sets the seat position forward (closer to steering wheel) and backwards.
+     * Max value indicates closest to wheel, min value indicates most rearward
+     * position.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_FORE_AFT_POS = 0x0B85 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat fore/aft move
+     *
+     * Moves the seat position forward and aft.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_FORE_AFT_MOVE = 0x0B86 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat backrest angle 1 position
+     *
+     * Backrest angle 1 is the actuator closest to the bottom of the seat.
+     * Max value indicates angling forward towards the steering wheel.
+     * Min value indicates full recline.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BACKREST_ANGLE_1_POS = 0x0B87 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat backrest angle 1 move
+     *
+     * Moves the backrest forward or recline.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BACKREST_ANGLE_1_MOVE = 0x0B88 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat backrest angle 2 position
+     *
+     * Backrest angle 2 is the next actuator up from the bottom of the seat.
+     * Max value indicates angling forward towards the steering wheel.
+     * Min value indicates full recline.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BACKREST_ANGLE_2_POS = 0x0B89 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat backrest angle 2 move
+     *
+     * Moves the backrest forward or recline.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BACKREST_ANGLE_2_MOVE = 0x0B8A + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat height position
+     *
+     * Sets the seat height.
+     * Max value indicates highest position.
+     * Min value indicates lowest position.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEIGHT_POS = 0x0B8B + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat height move
+     *
+     * Moves the seat height.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEIGHT_MOVE = 0x0B8C + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat depth position
+     *
+     * Sets the seat depth, distance from back rest to front edge of seat.
+     * Max value indicates longest depth position.
+     * Min value indicates shortest position.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_DEPTH_POS = 0x0B8D + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat depth move
+     *
+     * Adjusts the seat depth.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_DEPTH_MOVE = 0x0B8E + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat tilt position
+     *
+     * Sets the seat tilt.
+     * Max value indicates front edge of seat higher than back edge.
+     * Min value indicates front edge of seat lower than back edge.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_TILT_POS = 0x0B8F + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat tilt move
+     *
+     * Tilts the seat.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_TILT_MOVE = 0x0B90 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Lumber fore/aft position
+     *
+     * Pushes the lumbar support forward and backwards
+     * Max value indicates most forward position.
+     * Min value indicates most rearward position.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_LUMBAR_FORE_AFT_POS = 0x0B91 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Lumbar fore/aft move
+     *
+     * Adjusts the lumbar support.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_LUMBAR_FORE_AFT_MOVE = 0x0B92 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Lumbar side support position
+     *
+     * Sets the amount of lateral lumbar support.
+     * Max value indicates widest lumbar setting (i.e. least support)
+     * Min value indicates thinnest lumbar setting.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_LUMBAR_SIDE_SUPPORT_POS = 0x0B93 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Lumbar side support move
+     *
+     * Adjusts the amount of lateral lumbar support.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x0B94 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Headrest height position
+     *
+     * Sets the headrest height.
+     * Max value indicates tallest setting.
+     * Min value indicates shortest setting.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_HEIGHT_POS = 0x0B95 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Headrest height move
+     *
+     * Moves the headrest up and down.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_HEIGHT_MOVE = 0x0B96 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Headrest angle position
+     *
+     * Sets the angle of the headrest.
+     * Max value indicates most upright angle.
+     * Min value indicates shallowest headrest angle.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_ANGLE_POS = 0x0B97 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Headrest angle move
+     *
+     * Adjusts the angle of the headrest
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_ANGLE_MOVE = 0x0B98 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Headrest fore/aft position
+     *
+     * Adjusts the headrest forwards and backwards.
+     * Max value indicates position closest to front of car.
+     * Min value indicates position closest to rear of car.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_FORE_AFT_POS = 0x0B99 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Headrest fore/aft move
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_FORE_AFT_MOVE = 0x0B9A + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Seat Occupancy
+     *
+     * Indicates whether a particular seat is occupied or not, to the best of the car's ability
+     * to determine. Valid values are from the VehicleSeatOccupancyState enum.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleSeatOccupancyState
+     */
+    SEAT_OCCUPANCY = 0x0BB0 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Window Position
+     *
+     * Min = window up / closed
+     * Max = window down / open
+     *
+     * For a window that may open out of plane (i.e. vent mode of sunroof) this
+     * parameter will work with negative values as follows:
+     *  Max = sunroof completely open
+     *  0 = sunroof closed.
+     *  Min = sunroof vent completely open
+     *
+     *  Note that in this mode, 0 indicates the window is closed.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    WINDOW_POS = 0x0BC0 + 0x10000000 + 0x03000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
+    /**
+     * Window Move
+     *
+     * Max = Open the window as fast as possible
+     * Min = Close the window as fast as possible
+     * Magnitude denotes relative speed.  I.e. +2 is faster than +1 in closing
+     * the window.
+     *
+     * For a window that may open out of plane (i.e. vent mode of sunroof) this
+     * parameter will work as follows:
+     *
+     * If sunroof is open:
+     *   Max = open the sunroof further, automatically stop when fully open.
+     *   Min = close the sunroof, automatically stop when sunroof is closed.
+     *
+     * If vent is open:
+     *   Max = close the vent, automatically stop when vent is closed.
+     *   Min = open the vent further, automatically stop when vent is fully open.
+     *
+     * If sunroof is in the closed position:
+     *   Max = open the sunroof, automatically stop when sunroof is fully open.
+     *   Min = open the vent, automatically stop when vent is fully open.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    WINDOW_MOVE = 0x0BC1 + 0x10000000 + 0x03000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
+    /**
+     * Window Lock
+     *
+     * True indicates windows are locked and can't be moved.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    WINDOW_LOCK = 0x0BC4 + 0x10000000 + 0x03000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
+    /**
+     * Vehicle Maps Service (VMS) message
+     *
+     * This property uses MIXED data to communicate vms messages.
+     *
+     * Its contents are to be interpreted as follows:
+     * the indices defined in VmsMessageIntegerValuesIndex are to be used to
+     * read from int32Values;
+     * bytes is a serialized VMS message as defined in the vms protocol
+     * which is opaque to the framework;
+     *
+     * IVehicle#get must always return StatusCode::NOT_AVAILABLE.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    VEHICLE_MAP_SERVICE = 0x0C00 + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * OBD2 Live Sensor Data
+     *
+     * Reports a snapshot of the current (live) values of the OBD2 sensors available.
+     *
+     * The configArray is set as follows:
+     *   configArray[0] = number of vendor-specific integer-valued sensors
+     *   configArray[1] = number of vendor-specific float-valued sensors
+     *
+     * The values of this property are to be interpreted as in the following example.
+     * Considering a configArray = {2,3}
+     * int32Values must be a vector containing Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + 2
+     * elements (that is, 33 elements);
+     * floatValues must be a vector containing Obd2FloatSensorIndex.LAST_SYSTEM_INDEX + 3
+     * elements (that is, 73 elements);
+     *
+     * It is possible for each frame to contain a different subset of sensor values, both system
+     * provided sensors, and vendor-specific ones. In order to support that, the bytes element
+     * of the property value is used as a bitmask,.
+     *
+     * bytes must have a sufficient number of bytes to represent the total number of possible
+     * sensors (in this case, 14 bytes to represent 106 possible values); it is to be read as
+     * a contiguous bitmask such that each bit indicates the presence or absence of a sensor
+     * from the frame, starting with as many bits as the size of int32Values, immediately
+     * followed by as many bits as the size of floatValues.
+     *
+     * For example, should bytes[0] = 0x4C (0b01001100) it would mean that:
+     *   int32Values[0 and 1] are not valid sensor values
+     *   int32Values[2 and 3] are valid sensor values
+     *   int32Values[4 and 5] are not valid sensor values
+     *   int32Values[6] is a valid sensor value
+     *   int32Values[7] is not a valid sensor value
+     * Should bytes[5] = 0x61 (0b01100001) it would mean that:
+     *   int32Values[32] is a valid sensor value
+     *   floatValues[0 thru 3] are not valid sensor values
+     *   floatValues[4 and 5] are valid sensor values
+     *   floatValues[6] is not a valid sensor value
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    OBD2_LIVE_FRAME = 0x0D00 + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * OBD2 Freeze Frame Sensor Data
+     *
+     * Reports a snapshot of the value of the OBD2 sensors available at the time that a fault
+     * occurred and was detected.
+     *
+     * A configArray must be provided with the same meaning as defined for OBD2_LIVE_FRAME.
+     *
+     * The values of this property are to be interpreted in a similar fashion as those for
+     * OBD2_LIVE_FRAME, with the exception that the stringValue field may contain a non-empty
+     * diagnostic troubleshooting code (DTC).
+     *
+     * A IVehicle#get request of this property must provide a value for int64Values[0].
+     * This will be interpreted as the timestamp of the freeze frame to retrieve. A list of
+     * timestamps can be obtained by a IVehicle#get of OBD2_FREEZE_FRAME_INFO.
+     *
+     * Should no freeze frame be available at the given timestamp, a response of NOT_AVAILABLE
+     * must be returned by the implementation. Because vehicles may have limited storage for
+     * freeze frames, it is possible for a frame request to respond with NOT_AVAILABLE even if
+     * the associated timestamp has been recently obtained via OBD2_FREEZE_FRAME_INFO.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    OBD2_FREEZE_FRAME = 0x0D01 + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * OBD2 Freeze Frame Information
+     *
+     * This property describes the current freeze frames stored in vehicle
+     * memory and available for retrieval via OBD2_FREEZE_FRAME.
+     *
+     * The values are to be interpreted as follows:
+     * each element of int64Values must be the timestamp at which a a fault code
+     * has been detected and the corresponding freeze frame stored, and each
+     * such element can be used as the key to OBD2_FREEZE_FRAME to retrieve
+     * the corresponding freeze frame.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    OBD2_FREEZE_FRAME_INFO = 0x0D02 + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * OBD2 Freeze Frame Clear
+     *
+     * This property allows deletion of any of the freeze frames stored in
+     * vehicle memory, as described by OBD2_FREEZE_FRAME_INFO.
+     *
+     * The configArray is set as follows:
+     *  configArray[0] = 1 if the implementation is able to clear individual freeze frames
+     *                   by timestamp, 0 otherwise
+     *
+     * IVehicle#set of this property is to be interpreted as follows:
+     *   if int64Values contains no elements, then all frames stored must be cleared;
+     *   if int64Values contains one or more elements, then frames at the timestamps
+     *   stored in int64Values must be cleared, and the others not cleared. Should the
+     *   vehicle not support selective clearing of freeze frames, this latter mode must
+     *   return NOT_AVAILABLE.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    OBD2_FREEZE_FRAME_CLEAR = 0x0D03 + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * Headlights State
+     *
+     * Return the current state of headlights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    HEADLIGHTS_STATE = 0x0E00 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * High beam lights state
+     *
+     * Return the current state of high beam lights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    HIGH_BEAM_LIGHTS_STATE = 0x0E01 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Fog light state
+     *
+     * Return the current state of fog lights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    FOG_LIGHTS_STATE = 0x0E02 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Hazard light status
+     *
+     * Return the current status of hazard lights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    HAZARD_LIGHTS_STATE = 0x0E03 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Headlight switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    HEADLIGHTS_SWITCH = 0x0E10 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * High beam light switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    HIGH_BEAM_LIGHTS_SWITCH = 0x0E11 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Fog light switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    FOG_LIGHTS_SWITCH = 0x0E12 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Hazard light switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    HAZARD_LIGHTS_SWITCH = 0x0E13 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Cabin lights
+     *
+     * Return current status of cabin lights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    CABIN_LIGHTS_STATE = 0x0F01 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Cabin lights switch
+     *
+     * The position of the physical switch which controls the cabin lights.
+     * This might be different than the CABIN_LIGHTS_STATE if the lights are on because a door
+     * is open or because of a voice command.
+     * For example, while the switch is in the "off" or "automatic" position.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    CABIN_LIGHTS_SWITCH = 0x0F02 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Reading lights
+     *
+     * Return current status of reading lights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    READING_LIGHTS_STATE = 0x0F03 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Reading lights switch
+     *
+     * The position of the physical switch which controls the reading lights.
+     * This might be different than the READING_LIGHTS_STATE if the lights are on because a door
+     * is open or because of a voice command.
+     * For example, while the switch is in the "off" or "automatic" position.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    READING_LIGHTS_SWITCH = 0x0F04 + 0x10000000 + 0x05000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+    /**
+     * Support customize permissions for vendor properties
+     *
+     * Implement this property if vehicle hal support customize vendor permissions feature.
+     * VehiclePropConfig.configArray is used to indicate vendor properties and permissions
+     * which selected for this vendor property. The permission must be one of enum in
+     * VehicleVendorPermission.
+     * The configArray is set as follows:
+     *      configArray[n] = propId : property ID for the vendor property
+     *      configArray[n+1] = one of enums in VehicleVendorPermission. It indicates the permission
+     *      for reading value of the property.
+     *      configArray[n+2] = one of enums in VehicleVendorPermission. It indicates the permission
+     *      for writing value of the property.
+     *
+     * For example:
+     * configArray = {
+     *      vendor_prop_1, PERMISSION_VENDOR_SEAT_READ, PERMISSION_VENDOR_SEAT_WRITE,
+     *      vendor_prop_2, PERMISSION_VENDOR_INFO, PERMISSION_NOT_ACCESSIBLE,
+     * }
+     * If vendor properties are not in this array, they will have the default vendor permission.
+     * If vendor chose PERMISSION_NOT_ACCESSIBLE, android will not have access to the property. In
+     * the example, Android can not write value for vendor_prop_2.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    SUPPORT_CUSTOMIZE_VENDOR_PERMISSION = 0x0F05 + 0x10000000 + 0x01000000
+            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+    /**
+     * Allow disabling optional featurs from vhal.
+     *
+     * This property reports optional features that should be disabled.
+     * All allowed optional features for the system is declared in Car service overlay,
+     * config_allowed_optional_car_features.
+     * This property allows disabling features defined in the overlay. Without this property,
+     * all the features declared in the overlay will be enabled.
+     *
+     * Value read should include all features disabled with ',' separation.
+     * ex) "com.android.car.user.CarUserNoticeService,storage_monitoring"
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    DISABLED_OPTIONAL_FEATURES = 0x0F06 + 0x10000000 + 0x01000000
+            + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+    /**
+     * Defines the initial Android user to be used during initialization.
+     *
+     * This property is called by the Android system when it initializes and it lets the HAL
+     * define which Android user should be started.
+     *
+     * This request is made by setting a VehiclePropValue (defined by InitialUserInfoRequest),
+     * and the HAL must respond with a property change event (defined by InitialUserInfoResponse).
+     * If the HAL doesn't respond after some time (defined by the Android system), the Android
+     * system will proceed as if HAL returned a response of action
+     * InitialUserInfoResponseAction:DEFAULT.
+     *
+     * For example, on first boot, the request could be:
+     *
+     * int32[0]: 42  // request id (arbitrary number set by Android system)
+     * int32[1]: 1   // InitialUserInfoRequestType::FIRST_BOOT
+     * int32[2]: 0   // id of current user (usersInfo.currentUser.userId)
+     * int32[3]: 1   // flag of current user (usersInfo.currentUser.flags = SYSTEM)
+     * int32[4]: 1   // number of existing users (usersInfo.numberUsers);
+     * int32[5]: 0   // user #0  (usersInfo.existingUsers[0].userId)
+     * int32[6]: 1   // flags of user #0  (usersInfo.existingUsers[0].flags)
+     *
+     * And if the HAL want to respond with the creation of an admin user called "Owner", the
+     * response would be:
+     *
+     * int32[0]: 42      // must match the request id from the request
+     * int32[1]:  2      // action = InitialUserInfoResponseAction::CREATE
+     * int32[2]: -10000  // userToSwitchOrCreate.userId (not used as user will be created)
+     * int32[3]:  8      // userToSwitchOrCreate.flags = ADMIN
+     * string: "||Owner" // userLocales + separator + userNameToCreate
+     *
+     * Notice the string value represents multiple values, separated by ||. The first value is the
+     * (optional) system locales for the user to be created (in this case, it's empty, meaning it
+     * will use Android's default value), while the second value is the (also optional) name of the
+     * to user to be created (when the type of response is InitialUserInfoResponseAction:CREATE).
+     * For example, to create the same "Owner" user with "en-US" and "pt-BR" locales, the string
+     * value of the response would be "en-US,pt-BR||Owner". As such, neither the locale nor the
+     * name can have || on it, although a single | is fine.
+     *
+     * NOTE: if the HAL doesn't support user management, then it should not define this property,
+     * which in turn would disable the other user-related properties (for example, the Android
+     * system would never issue them and user-related requests from the HAL layer would be ignored
+     * by the Android System). But if it supports user management, then it must support all core
+     * user-related properties (INITIAL_USER_INFO, SWITCH_USER, CREATE_USER, and REMOVE_USER).
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    INITIAL_USER_INFO = 0x0F07 + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * Defines a request to switch the foreground Android user.
+     *
+     * This property is used primarily by the Android System to inform the HAL that the
+     * current foreground Android user is switching, but it could also be used by the HAL to request
+     * the Android system to switch users - the
+     *
+     * When the request is made by Android, it sets a VehiclePropValue and the HAL must responde
+     * with a property change event; when the HAL is making the request, it must also do it through
+     * a property change event (the main difference is that the request id will be positive in the
+     * former case, and negative in the latter; the SwitchUserMessageType will also be different).
+     *
+     * The format of both request is defined by SwitchUserRequest and the format of the response
+     * (when needed) is defined by SwitchUserResponse. How the HAL (or Android System) should
+     * proceed depends on the message type (which is defined by the SwitchUserMessageType
+     * parameter), as defined below.
+     *
+     * 1.LEGACY_ANDROID_SWITCH
+     * -----------------------
+     *
+     * Called by the Android System to indicate the Android user is about to change, when the change
+     * request was made in a way that is not integrated with the HAL (for example, through
+     * adb shell am switch-user).
+     *
+     * The HAL can switch its internal user once it receives this request, but it doesn't need to
+     * reply back to the Android System. If its internal user cannot be changed for some reason,
+     * then it must wait for the SWITCH_USER(type=ANDROID_POST_SWITCH) call to recover
+     * (for example, it could issue a SWITCH_USER(type=VEHICLE_REQUEST) to switch back to
+     * the previous user), but ideally it should never fail (as switching back could result in a
+     * confusing experience for the end user).
+     *
+     * For example, if the system have users (0, 10, 11) and it's switching from 0 to 11 (where none
+     * of them have any special flag), the request would be:
+     *
+     * int32[0]:  42  // request id
+     * int32[1]:  1   // SwitchUserMessageType::LEGACY_ANDROID_SWITCH
+     * int32[2]:  11  // target user id
+     * int32[3]:  0   // target user flags (none)
+     * int32[4]:  10  // current user
+     * int32[5]:  0   // current user flags (none)
+     * int32[6]:  3   // number of users
+     * int32[7]:  0   // user #0 (Android user id 0)
+     * int32[8]:  0   // flags of user #0 (none)
+     * int32[9]:  10  // user #1 (Android user id 10)
+     * int32[10]: 0   // flags of user #1 (none)
+     * int32[11]: 11  // user #2 (Android user id 11)
+     * int32[12]: 0   // flags of user #2 (none)
+     *
+     * 2.ANDROID_SWITCH
+     * ----------------
+     * Called by the Android System to indicate the Android user is about to change, but Android
+     * will wait for the HAL's response (up to some time) before proceeding.
+     *
+     * The HAL must switch its internal user once it receives this request, then respond back to
+     * Android with a SWITCH_USER(type=VEHICLE_RESPONSE) indicating whether its internal
+     * user was switched or not (through the SwitchUserStatus enum).
+     *
+     * For example, if Android has users (0, 10, 11) and it's switching from 10 to 11 (where
+     * none of them have any special flag), the request would be:
+     *
+     * int32[0]:  42  // request id
+     * int32[1]:  2   // SwitchUserMessageType::ANDROID_SWITCH
+     * int32[2]:  11  // target user id
+     * int32[3]:  0   // target user flags (none)
+     * int32[4]:  10  // current user
+     * int32[5]:  0   // current user flags (none)
+     * int32[6]:  3   // number of users
+     * int32[7]:  0   // 1st user (user 0)
+     * int32[8]:  1   // 1st user flags (SYSTEM)
+     * int32[9]:  10  // 2nd user (user 10)
+     * int32[10]: 0   // 2nd user flags (none)
+     * int32[11]: 11  // 3rd user (user 11)
+     * int32[12]: 0   // 3rd user flags (none)
+     *
+     * If the request succeeded, the HAL must update the property with:
+     *
+     * int32[0]: 42  // request id
+     * int32[1]: 3   // messageType = SwitchUserMessageType::VEHICLE_RESPONSE
+     * int32[2]: 1   // status = SwitchUserStatus::SUCCESS
+     *
+     * But if it failed, the response would be something like:
+     *
+     * int32[0]: 42   // request id
+     * int32[1]: 3    // messageType = SwitchUserMessageType::VEHICLE_RESPONSE
+     * int32[2]: 2    // status = SwitchUserStatus::FAILURE
+     * string: "108-D'OH!" // OEM-specific error message
+     *
+     * 3.VEHICLE_RESPONSE
+     * ------------------
+     * Called by the HAL to indicate whether a request of type ANDROID_SWITCH should proceed or
+     * abort - see the ANDROID_SWITCH section above for more info.
+     *
+     * 4.VEHICLE_REQUEST
+     * ------------------
+     * Called by the HAL to request that the current foreground Android user is switched.
+     *
+     * This is useful in situations where Android started as one user, but the vehicle identified
+     * the driver as another user. For example, user A unlocked the car using the key fob of user B;
+     * the INITIAL_USER_INFO request returned user B, but then a face recognition subsubsystem
+     * identified the user as A.
+     *
+     * The HAL makes this request by a property change event (passing a negative request id), and
+     * the Android system will response by issue an ANDROID_POST_SWITCH call which the same
+     * request id.
+     *
+     * For example, if the current foreground Android user is 10 and the HAL asked it to switch to
+     * 11, the request would be:
+     *
+     * int32[0]: -108  // request id
+     * int32[1]: 4     // messageType = SwitchUserMessageType::VEHICLE_REQUEST
+     * int32[2]: 11    // Android user id
+     *
+     * If the request succeeded and Android has 3 users (0, 10, 11), the response would be:
+     *
+     * int32[0]: -108 // request id
+     * int32[1]:  5   // messageType = SwitchUserMessageType::ANDROID_POST_SWITCH
+     * int32[2]:  11  // target user id
+     * int32[3]:  0   // target user id flags (none)
+     * int32[4]:  11  // current user
+     * int32[5]:  0   // current user flags (none)
+     * int32[6]:  3   // number of users
+     * int32[7]:  0   // 1st user (user 0)
+     * int32[8]:  0   // 1st user flags (none)
+     * int32[9]:  10  // 2nd user (user 10)
+     * int32[10]: 4   // 2nd user flags (none)
+     * int32[11]: 11  // 3rd user (user 11)
+     * int32[12]: 3   // 3rd user flags (none)
+     *
+     * Notice that both the current and target user ids are the same - if the request failed, then
+     * they would be different (i.e, target user would be 11, but current user would still be 10).
+     *
+     * 5.ANDROID_POST_SWITCH
+     * ---------------------
+     * Called by the Android System after a request to switch a user was made.
+     *
+     * This property is called after switch requests of any type (i.e., LEGACY_ANDROID_SWITCH,
+     * ANDROID_SWITCH, or VEHICLE_REQUEST) and can be used to determine if the request succeeded or
+     * failed:
+     *
+     * 1. When it succeeded, it's called when the Android user is in the unlocked state and the
+     *    value of the current and target users ids in the response are the same. This would be
+     *    equivalent to receiving an Intent.ACTION_USER_UNLOCKED in an Android app.
+     * 2. When it failed it's called right away and the value of the current and target users ids
+     *    in the response are different (as the current user didn't change to the target).
+     * 3. If a new switch request is made before the HAL responded to the previous one or before
+     *    the user was unlocked, then the ANDROID_POST_SWITCH request is not made. For example,
+     *    the driver could accidentally switch to the wrong user which has lock credentials, then
+     *    switch to the right one before entering the credentials.
+     *
+     * The HAL can update its internal state once it receives this request, but it doesn't need to
+     * reply back to the Android System.
+     *
+     * Request: the first N values as defined by INITIAL_USER_INFO (where the request-specific
+     * value at index 1 is SwitchUserMessageType::ANDROID_POST_SWITCH), then 2 more values for the
+     * target user id (i.e., the Android user id that was requested to be switched to) and its flags
+     * (as defined by  UserFlags).
+     *
+     * Response: none.
+     *
+     * Example: see VEHICLE_REQUEST section above.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SWITCH_USER = 0x0F08 + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * Called by the Android System after an Android user was created.
+     *
+     * The HAL can use this property to create its equivalent user.
+     *
+     * This is an async request: Android makes the request by setting a VehiclePropValue, and HAL
+     * must respond with a property change indicating whether the request succeeded or failed. If
+     * it failed, the Android system will remove the user.
+     *
+     * The format of the request is defined by CreateUserRequest and the format of the response by
+     * CreateUserResponse.
+     *
+     * For example, if system had 2 users (0 and 10) and a 3rd one (which is an ephemeral guest) was
+     * created, the request would be:
+     *
+     * int32[0]: 42  // request id
+     * int32[1]: 11  // Android id of the created user
+     * int32[2]: 6   // Android flags (ephemeral guest) of the created user
+     * int32[3]: 10  // current user
+     * int32[4]: 0   // current user flags (none)
+     * int32[5]: 3   // number of users
+     * int32[6]: 0   // 1st user (user 0)
+     * int32[7]: 0   // 1st user flags (none)
+     * int32[8]: 10  // 2nd user (user 10)
+     * int32[9]: 0   // 2nd user flags (none)
+     * int32[19]: 11 // 3rd user (user 11)
+     * int32[11]: 6  // 3rd user flags (ephemeral guest)
+     * string: "ElGuesto" // name of the new user
+     *
+     * Then if the request succeeded, the HAL would return:
+     *
+     * int32[0]: 42  // request id
+     * int32[1]: 1   // CreateUserStatus::SUCCESS
+     *
+     * But if it failed:
+     *
+     * int32[0]: 42  // request id
+     * int32[1]: 2   // CreateUserStatus::FAILURE
+     * string: "D'OH!" // The meaning is a blackbox - it's passed to the caller (like Settings UI),
+     *                 // which in turn can take the proper action.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    CREATE_USER = 0x0F09 + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * Called by the Android System after an Android user was removed.
+     *
+     * The HAL can use this property to remove its equivalent user.
+     *
+     * This is write-only call - the Android System is not expecting a reply from the HAL. Hence,
+     * this request should not fail - if the equivalent HAL user cannot be removed, then HAL should
+     * mark it as inactive or recover in some other way.
+     *
+     * The request is made by setting the VehiclePropValue with the contents defined by
+     * RemoveUserRequest.
+     *
+     * For example, if system had 3 users (0, 10, and 11) and user 11 was removed, the request
+     * would be:
+     *
+     * int32[0]: 42  // request id
+     * int32[1]: 11  // (Android user id of the removed user)
+     * int32[2]: 0   // (Android user flags of the removed user)
+     * int32[3]: 10  // current user
+     * int32[4]: 0   // current user flags (none)
+     * int32[5]: 2   // number of users
+     * int32[6]: 0   // 1st user (user 0)
+     * int32[7]: 0   // 1st user flags (none)
+     * int32[8]: 10  // 2nd user (user 10)
+     * int32[9]: 0   // 2nd user flags (none)
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:WRITE
+     */
+    REMOVE_USER = 0x0F0A + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * Property used to associate (or query the association) the current user with vehicle-specific
+     * identification mechanisms (such as key FOB).
+     *
+     * This is an optional user management property - the OEM could still support user management
+     * without defining it. In fact, this property could be used without supporting the core
+     * user-related functions described on INITIAL_USER_INFO.
+     *
+     * To query the association, the Android system gets the property, passing a VehiclePropValue
+     * containing the types of associations are being queried, as defined by
+     * UserIdentificationGetRequest. The HAL must return right away, returning a VehiclePropValue
+     * with a UserIdentificationResponse. Notice that user identification should have already
+     * happened while system is booting up and the VHAL implementation should only return the
+     * already identified association (like the key FOB used to unlock the car), instead of starting
+     * a new association from the get call.
+     *
+     * To associate types, the Android system sets the property, passing a VehiclePropValue
+     * containing the types and values of associations being set, as defined by the
+     * UserIdentificationSetRequest. The HAL will then use a property change event (whose
+     * VehiclePropValue is defined by UserIdentificationResponse) indicating the current status of
+     * the types after the request.
+     *
+     * For example, to query if the current user (10) is associated with the FOB that unlocked the
+     * car and a custom mechanism provided by the OEM, the request would be:
+     *
+     * int32[0]: 42  // request id
+     * int32[1]: 10  (Android user id)
+     * int32[2]: 0   (Android user flags)
+     * int32[3]: 2   (number of types queried)
+     * int32[4]: 1   (1st type queried, UserIdentificationAssociationType::KEY_FOB)
+     * int32[5]: 101 (2nd type queried, UserIdentificationAssociationType::CUSTOM_1)
+     *
+     * If the user is associated with the FOB but not with the custom mechanism, the response would
+     * be:
+     *
+     * int32[0]: 42  // request id
+     * int32[1]: 2   (number of associations in the response)
+     * int32[2]: 1   (1st type: UserIdentificationAssociationType::KEY_FOB)
+     * int32[3]: 2   (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER)
+     * int32[4]: 101 (2st type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[5]: 4   (2nd value: UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER)
+     *
+     * Then to associate the user with the custom mechanism, a set request would be made:
+     *
+     * int32[0]: 43  // request id
+     * int32[1]: 10  (Android user id)
+     * int32[2]: 0   (Android user flags)
+     * int32[3]: 1   (number of associations being set)
+     * int32[4]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[5]: 1   (1st value: UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER)
+     *
+     * If the request succeeded, the response would be simply:
+     *
+     * int32[0]: 43  // request id
+     * int32[1]: 1   (number of associations in the response)
+     * int32[2]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[3]: 1   (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER)
+     *
+     * Notice that the set request adds associations, but doesn't remove the existing ones. In the
+     * example above, the end state would be 2 associations (FOB and CUSTOM_1). If we wanted to
+     * associate the user with just CUSTOM_1 but not FOB, then the request should have been:
+     *
+     * int32[0]: 43  // request id
+     * int32[1]: 10  (Android user id)
+     * int32[2]: 2   (number of types set)
+     * int32[3]: 1   (1st type: UserIdentificationAssociationType::KEY_FOB)
+     * int32[4]: 2   (1st value: UserIdentificationAssociationValue::DISASSOCIATE_CURRENT_USER)
+     * int32[5]: 101 (2nd type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[6]: 1   (2nd value: UserIdentificationAssociationValue::ASSOCIATE_CURRENT_USER)
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    USER_IDENTIFICATION_ASSOCIATION = 0x0F0B + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * Enable/request an EVS service.
+     *
+     * The property provides a generalized way to trigger EVS services.  VHAL
+     * should use this property to request Android to start or stop EVS service.
+     *
+     *  int32Values[0] = a type of the EVS service. The value must be one of enums in
+     *                   EvsServiceType.
+     *  int32Values[1] = the state of the EVS service. The value must be one of enums in
+     *                   EvsServiceState.
+     *
+     * For example, to enable rear view EVS service, android side can set the property value as
+     * [EvsServiceType::REAR_VIEW, EvsServiceState::ON].
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    EVS_SERVICE_REQUEST = 0x0F10 + 0x10000000 + 0x01000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    /**
+     * Defines a request to apply power policy.
+     *
+     * VHAL sets this property to change car power policy. Car power policy service subscribes to
+     * this property and actually changes the power policy.
+     * The request is made by setting the VehiclePropValue with the ID of a power policy which is
+     * defined at /vendor/etc/power_policy.xml. If the given ID is not defined, car power policy
+     * service ignores the request and the current power policy is maintained.
+     *
+     *   string: "sample_policy_id" // power policy ID
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    POWER_POLICY_REQ = 0x0F21 + 0x10000000 + 0x01000000
+            + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+    /**
+     * Defines a request to set the power polic group used to decide a default power policy per
+     * power status transition.
+     *
+     * VHAL sets this property with the ID of a power policy group in order to set the default power
+     * policy applied at power status transition. Power policy groups are defined at
+     * /vendor/etc/power_policy.xml. If the given ID is not defined, car power policy service
+     * ignores the request.
+     * Car power policy service subscribes to this property and sets the power policy group.
+     * The actual application of power policy takes place when the system power status changes and
+     * there is a valid mapped power policy for the new power status.
+     *
+     *   string: "sample_policy_group_id" // power policy group ID
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    POWER_POLICY_GROUP_REQ = 0x0F22 + 0x10000000 + 0x01000000
+            + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+    /**
+     * Notifies the current power policy to VHAL layer.
+     *
+     * Car power policy service sets this property when the current power policy is changed.
+     *
+     *   string: "sample_policy_id" // power policy ID
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    CURRENT_POWER_POLICY = 0x0F23 + 0x10000000 + 0x01000000
+            + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+    /**
+     * Defines an event that car watchdog updates to tell it's alive.
+     *
+     * Car watchdog sets this property to system uptime in milliseconds at every 3 second.
+     * During the boot, the update may take longer time.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    WATCHDOG_ALIVE = 0xF31 + 0x10000000 + 0x01000000
+            + 0x00500000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64
+    /**
+     * Defines a process terminated by car watchdog and the reason of termination.
+     *
+     *   int32Values[0]: 1         // ProcessTerminationReason showing why a process is terminated.
+     *   string: "/system/bin/log" // Process execution command.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    WATCHDOG_TERMINATED_PROCESS = 0x0F32 + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * Defines an event that VHAL signals to car watchdog as a heartbeat.
+     *
+     * If VHAL supports this property, VHAL should write system uptime to this property at every 3
+     * second. Car watchdog subscribes to this property and checks if the property is updated at
+     * every 3 second. With the buffer time of 3 second, car watchdog waits for a heart beat to be
+     * signaled up to 6 seconds from the last heart beat. If it isn’t, car watchdog considers
+     * VHAL unhealthy and terminates it.
+     * If this property is not supported by VHAL, car watchdog doesn't check VHAL health status.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    VHAL_HEARTBEAT = 0x0F33 + 0x10000000 + 0x01000000
+            + 0x00500000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64
+    /**
+     * Starts the ClusterUI in cluster display.
+     *
+     * int32: the type of ClusterUI to show
+     *    0 indicates ClusterHome, that is a home screen of cluster display, and provides
+     *        the default UI and a kind of launcher functionality for cluster display.
+     *    the other values are followed by OEM's definition.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    CLUSTER_SWITCH_UI = 0x0F34 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Changes the state of the cluster display.
+     *
+     * Bounds: the area to render the cluster Activity.
+     * Inset: the area which Activity should avoid from placing any important
+     *     information.
+     *
+     * int32[0]: on/off: 0 - off, 1 - on, -1 - don't care
+     * int32[1]: Bounds - left: positive number - left position in pixels
+                                -1 - don't care (should set all Bounds fields)
+     * int32[2]: Bounds - top:    same format with 'left'
+     * int32[3]: Bounds - right:  same format with 'left'
+     * int32[4]: Bounds - bottom: same format with 'left'
+     * int32[5]: Inset - left: positive number - actual left inset value in pixels
+                               -1 - don't care (should set "don't care" all Inset fields)
+     * int32[6]: Inset - top:    same format with 'left'
+     * int32[7]: Inset - right:  same format with 'left'
+     * int32[8]: Inset - bottom: same format with 'left'
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    CLUSTER_DISPLAY_STATE = 0x0F35 + 0x10000000 + 0x01000000
+            + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    /**
+     * Reports the current display state and ClusterUI state.
+     *
+     * ClusterHome will send this message when it handles CLUSTER_SWITCH_UI, CLUSTER_DISPLAY_STATE.
+     *
+     * In addition, ClusterHome should send this message when it starts for the first time.
+     * When ClusterOS receives this message and if the internal expectation is different with the
+     * received message, then it should send CLUSTER_SWITCH_UI, CLUSTER_DISPLAY_STATE again to
+     * match the state.
+     *
+     * int32[0]: on/off: 0 - off, 1 - on
+     * int32[1]: Bounds - left
+     * int32[2]: Bounds - top
+     * int32[3]: Bounds - right
+     * int32[4]: Bounds - bottom
+     * int32[5]: Inset - left
+     * int32[6]: Inset - top
+     * int32[7]: Inset - right
+     * int32[8]: Inset - bottom
+     * int32[9]: the type of ClusterUI in the fullscreen or main screen.
+     *    0 indicates ClusterHome.
+     *    the other values are followed by OEM's definition.
+     * int32[10]: the type of ClusterUI in sub screen if the currently two UIs are shown.
+     *    -1 indicates the area isn't used any more.
+     * bytes: the array to represent the availability of ClusterUI.
+     *     0 indicates non-available and 1 indicates available.
+     *     For example, let's assume a car supports 3 OEM defined ClusterUI like HOME, MAPS, CALL,
+     *     and it only supports CALL UI only when the cellular network is available. Then, if the
+     *     nework is avaibale, it'll send [1 1 1], and if it's out of network, it'll send [1 1 0].
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    CLUSTER_REPORT_STATE = 0x0F36 + 0x10000000 + 0x01000000
+            + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+    /**
+     * Requests to change the cluster display state to show some ClusterUI.
+     *
+     * When the current display state is off and ClusterHome sends this message to ClusterOS to
+     * request to turn the display on to show some specific ClusterUI.
+     * ClusterOS should response this with CLUSTER_DISPLAY_STATE.
+     *
+     * int32: the type of ClusterUI to show
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    CLUSTER_REQUEST_DISPLAY = 0x0F37 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Informs the current navigation state.
+     *
+     * bytes: the serialized message of NavigationStateProto.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    CLUSTER_NAVIGATION_STATE = 0x0F38 + 0x10000000 + 0x01000000
+            + 0x00700000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BYTES
+    /**
+     * Electronic Toll Collection card type.
+     *
+     * This property indicates the type of ETC card in this vehicle.
+     * If the head unit is aware of an ETC card attached to the vehicle, this property should
+     * return the type of card attached; otherwise, this property should be UNAVAILABLE.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum ElectronicTollCollectionCardType
+     */
+    ELECTRONIC_TOLL_COLLECTION_CARD_TYPE = 0x0F39 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+    /**
+     * Electronic Toll Collection card status.
+     *
+     * This property indicates the status of ETC card in this vehicle.
+     * If the head unit is aware of an ETC card attached to the vehicle,
+     * ELECTRONIC_TOLL_COLLECTION_CARD_TYPE gives that status of the card; otherwise,
+     * this property should be UNAVAILABLE.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum ElectronicTollCollectionCardStatus
+     */
+    ELECTRONIC_TOLL_COLLECTION_CARD_STATUS = 0x0F3A + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.aidl
new file mode 100644
index 0000000..76e38e3
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Property config defines the capabilities of it. User of the API
+ * must first get the property config to understand the output from get()
+ * commands and also to ensure that set() or events commands are in sync with
+ * the expected output.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehiclePropertyAccess {
+    NONE = 0x00,
+
+    READ = 0x01,
+    WRITE = 0x02,
+    READ_WRITE = 0x03,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.aidl
new file mode 100644
index 0000000..57228db
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.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.automotive.vehicle;
+
+/**
+ * This describes how value of property can change.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehiclePropertyChangeMode {
+    /**
+     * Property of this type must never be changed. Subscription is not supported
+     * for these properties.
+     */
+    STATIC = 0x00,
+
+    /**
+     * Properties of this type must report when there is a change.
+     * IVehicle#get call must return the current value.
+     * Set operation for this property is assumed to be asynchronous. When the
+     * property is read (using IVehicle#get) after IVehicle#set, it may still
+     * return old value until underlying H/W backing this property has actually
+     * changed the state. Once state is changed, the property must dispatch
+     * changed value as event.
+     */
+    ON_CHANGE = 0x01,
+
+    /**
+     * Properties of this type change continuously and require a fixed rate of
+     * sampling to retrieve the data.  Implementers may choose to send extra
+     * notifications on significant value changes.
+     */
+    CONTINUOUS = 0x02,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyGroup.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyGroup.aidl
new file mode 100644
index 0000000..a2cbdec
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyGroup.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehiclePropertyGroup {
+    /**
+     * Properties declared in AOSP must use this flag.
+     */
+    SYSTEM = 0x10000000,
+
+    /**
+     * Properties declared by vendors must use this flag.
+     */
+    VENDOR = 0x20000000,
+
+    MASK = 0xf0000000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl
new file mode 100644
index 0000000..400e256
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.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.automotive.vehicle;
+
+/**
+ * Property status is a dynamic value that may change based on the vehicle state.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehiclePropertyStatus {
+    /** Property is available and behaving normally */
+    AVAILABLE = 0x00,
+    /**
+     * A property in this state is not available for reading and writing.  This
+     * is a transient state that depends on the availability of the underlying
+     * implementation (e.g. hardware or driver). It MUST NOT be used to
+     * represent features that this vehicle is always incapable of.  A get() of
+     * a property in this state MAY return an undefined value, but MUST
+     * correctly describe its status as UNAVAILABLE A set() of a property in
+     * this state MAY return NOT_AVAILABLE. The HAL implementation MUST ignore
+     * the value of the status field when writing a property value coming from
+     * Android.
+     */
+    UNAVAILABLE = 0x01,
+    /** There is an error with this property. */
+    ERROR = 0x02,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyType.aidl
new file mode 100644
index 0000000..62d26de
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyType.aidl
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Enumerates supported data type for VehicleProperty.
+ *
+ * Used to create property ID in VehicleProperty enum.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehiclePropertyType {
+    STRING = 0x00100000,
+    BOOLEAN = 0x00200000,
+    INT32 = 0x00400000,
+    INT32_VEC = 0x00410000,
+    INT64 = 0x00500000,
+    INT64_VEC = 0x00510000,
+    FLOAT = 0x00600000,
+    FLOAT_VEC = 0x00610000,
+    BYTES = 0x00700000,
+
+    /**
+     * Any combination of scalar or vector types. The exact format must be
+     * provided in the description of the property.
+     *
+     * For vendor MIXED type properties, configArray needs to be formatted in this
+     * structure.
+     * configArray[0], 1 indicates the property has a String value
+     * configArray[1], 1 indicates the property has a Boolean value .
+     * configArray[2], 1 indicates the property has an Integer value.
+     * configArray[3], the number indicates the size of Integer[] in the property.
+     * configArray[4], 1 indicates the property has a Long value.
+     * configArray[5], the number indicates the size of Long[] in the property.
+     * configArray[6], 1 indicates the property has a Float value.
+     * configArray[7], the number indicates the size of Float[] in the property.
+     * configArray[8], the number indicates the size of byte[] in the property.
+     * For example:
+     * {@code configArray = {1, 1, 1, 3, 0, 0, 0, 0, 0}} indicates the property has
+     * a String value, a Boolean value, an Integer value and an array with 3 integers.
+     */
+    MIXED = 0x00e00000,
+
+    MASK = 0x00ff0000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleSeatOccupancyState.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleSeatOccupancyState.aidl
new file mode 100644
index 0000000..3a08a51
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleSeatOccupancyState.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by seat occupancy to enumerate the current occupancy state of the seat.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleSeatOccupancyState {
+    UNKNOWN = 0,
+    VACANT = 1,
+    OCCUPIED = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleTurnSignal.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleTurnSignal.aidl
new file mode 100644
index 0000000..f0f46ad
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleTurnSignal.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleTurnSignal {
+    NONE = 0x00,
+    RIGHT = 0x01,
+    LEFT = 0x02,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleUnit.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleUnit.aidl
new file mode 100644
index 0000000..9c3f8f9
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleUnit.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.automotive.vehicle;
+
+/**
+ * Units used for int or float type with no attached enum types.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleUnit {
+    SHOULD_NOT_USE = 0x000,
+    METER_PER_SEC = 0x01,
+    RPM = 0x02,
+    HERTZ = 0x03,
+    PERCENTILE = 0x10,
+    MILLIMETER = 0x20,
+    METER = 0x21,
+    KILOMETER = 0x23,
+    MILE = 0x24,
+    CELSIUS = 0x30,
+    FAHRENHEIT = 0x31,
+    KELVIN = 0x32,
+    MILLILITER = 0x40,
+    LITER = 0x41,
+    /**
+     * deprecated. Use US_GALLON instead.
+     */
+    GALLON = 0x42,
+    US_GALLON = 0x42,
+    IMPERIAL_GALLON = 0x43,
+    NANO_SECS = 0x50,
+    SECS = 0x53,
+    YEAR = 0x59,
+    WATT_HOUR = 0x60,
+    MILLIAMPERE = 0x61,
+    MILLIVOLT = 0x62,
+    MILLIWATTS = 0x63,
+    AMPERE_HOURS = 0x64,
+    KILOWATT_HOUR = 0x65,
+    KILOPASCAL = 0x70,
+    PSI = 0x71,
+    BAR = 0x72,
+    DEGREES = 0x80,
+    MILES_PER_HOUR = 0x90,
+    KILOMETERS_PER_HOUR = 0x91,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleVendorPermission.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleVendorPermission.aidl
new file mode 100644
index 0000000..29ad170
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleVendorPermission.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by SUPPORT_CUSTOMIZE_VENDOR_PERMISSION to indicate the permission of vendor properties.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleVendorPermission {
+    PERMISSION_DEFAULT = 0x00000000,
+    PERMISSION_SET_VENDOR_CATEGORY_WINDOW = 0X00000001,
+    PERMISSION_GET_VENDOR_CATEGORY_WINDOW = 0x00000002,
+    PERMISSION_SET_VENDOR_CATEGORY_DOOR = 0x00000003,
+    PERMISSION_GET_VENDOR_CATEGORY_DOOR = 0x00000004,
+    PERMISSION_SET_VENDOR_CATEGORY_SEAT = 0x00000005,
+    PERMISSION_GET_VENDOR_CATEGORY_SEAT = 0x00000006,
+    PERMISSION_SET_VENDOR_CATEGORY_MIRROR = 0x00000007,
+    PERMISSION_GET_VENDOR_CATEGORY_MIRROR = 0x00000008,
+    PERMISSION_SET_VENDOR_CATEGORY_INFO = 0x00000009,
+    PERMISSION_GET_VENDOR_CATEGORY_INFO = 0x0000000A,
+    PERMISSION_SET_VENDOR_CATEGORY_ENGINE = 0x0000000B,
+    PERMISSION_GET_VENDOR_CATEGORY_ENGINE = 0x0000000C,
+    PERMISSION_SET_VENDOR_CATEGORY_HVAC = 0x0000000D,
+    PERMISSION_GET_VENDOR_CATEGORY_HVAC = 0x0000000E,
+    PERMISSION_SET_VENDOR_CATEGORY_LIGHT = 0x0000000F,
+    PERMISSION_GET_VENDOR_CATEGORY_LIGHT = 0x00000010,
+    PERMISSION_SET_VENDOR_CATEGORY_1 = 0x00010000,
+    PERMISSION_GET_VENDOR_CATEGORY_1 = 0x00011000,
+    PERMISSION_SET_VENDOR_CATEGORY_2 = 0x00020000,
+    PERMISSION_GET_VENDOR_CATEGORY_2 = 0x00021000,
+    PERMISSION_SET_VENDOR_CATEGORY_3 = 0x00030000,
+    PERMISSION_GET_VENDOR_CATEGORY_3 = 0x00031000,
+    PERMISSION_SET_VENDOR_CATEGORY_4 = 0x00040000,
+    PERMISSION_GET_VENDOR_CATEGORY_4 = 0x00041000,
+    PERMISSION_SET_VENDOR_CATEGORY_5 = 0x00050000,
+    PERMISSION_GET_VENDOR_CATEGORY_5 = 0x00051000,
+    PERMISSION_SET_VENDOR_CATEGORY_6 = 0x00060000,
+    PERMISSION_GET_VENDOR_CATEGORY_6 = 0x00061000,
+    PERMISSION_SET_VENDOR_CATEGORY_7 = 0x00070000,
+    PERMISSION_GET_VENDOR_CATEGORY_7 = 0x00071000,
+    PERMISSION_SET_VENDOR_CATEGORY_8 = 0x00080000,
+    PERMISSION_GET_VENDOR_CATEGORY_8 = 0x00081000,
+    PERMISSION_SET_VENDOR_CATEGORY_9 = 0x00090000,
+    PERMISSION_GET_VENDOR_CATEGORY_9 = 0x00091000,
+    PERMISSION_SET_VENDOR_CATEGORY_10 = 0x000A0000,
+    PERMISSION_GET_VENDOR_CATEGORY_10 = 0x000A1000,
+    PERMISSION_NOT_ACCESSIBLE = 0xF0000000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsAvailabilityStateIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsAvailabilityStateIntegerValuesIndex.aidl
new file mode 100644
index 0000000..def7c28
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsAvailabilityStateIntegerValuesIndex.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/**
+ * An availability state is sent to the subscribers in response to a change in the available
+ * layers as part of a VmsMessageType.AVAILABILITY_CHANGE message, or in response to a
+ * VmsMessageType.AVAILABILITY_REQUEST message as part of a VmsMessageType.AVAILABILITY_RESPONSE.
+ * The VMS service issues monotonically increasing sequence numbers, and in case a subscriber
+ * receives a smaller sequence number, it should ignore the message. An available associated layer
+ * is a layer with a list of publisher IDs:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of publisher IDs (N)
+ * - N x publisher ID
+ */
+@VintfStability
+@Backing(type="int")
+enum VmsAvailabilityStateIntegerValuesIndex {
+    /*
+     * The message type as enumerated by VmsMessageType enum.
+     */
+    MESSAGE_TYPE = 0,
+    SEQUENCE_NUMBER = 1,
+    NUMBER_OF_ASSOCIATED_LAYERS = 2,
+    LAYERS_START = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsBaseMessageIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsBaseMessageIntegerValuesIndex.aidl
new file mode 100644
index 0000000..a82ce0b
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsBaseMessageIntegerValuesIndex.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Every VMS message starts with the type of the message from the VmsMessageType enum.
+ * Messages with no parameters such as VmsMessageType.AVAILABILITY_REQUEST,
+ * VmsMessageType.SUBSCRIPTIONS_REQUEST and VmsMessageType.DATA are also based on this enum.
+ */
+@VintfStability
+@Backing(type="int")
+enum VmsBaseMessageIntegerValuesIndex {
+    /*
+     * The message type as enumerated by VmsMessageType enum.
+     */
+    MESSAGE_TYPE = 0,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageType.aidl
new file mode 100644
index 0000000..6f03e37
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageType.aidl
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.vehicle;
+
+/**
+ * This enum lists the types of supported VMS messages. It is used as the first
+ * integer in the vehicle property integers array and determines how the rest of
+ * the message is decoded.
+ */
+@VintfStability
+@Backing(type="int")
+enum VmsMessageType {
+    /**
+     * A request from the subscribers to the VMS service to subscribe to a layer.
+     *
+     * This message type uses enum VmsMessageWithLayerIntegerValuesIndex.
+     */
+    SUBSCRIBE = 1,
+    /**
+     * A request from the subscribers to the VMS service to subscribe to a layer from a specific
+     * publisher.
+     *
+     * This message type uses enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.
+     */
+    SUBSCRIBE_TO_PUBLISHER = 2,
+    /**
+     * A request from the subscribers to the VMS service to unsubscribes from a layer.
+     *
+     * This message type uses enum VmsMessageWithLayerIntegerValuesIndex.
+     */
+    UNSUBSCRIBE = 3,
+    /**
+     * A request from the subscribers to the VMS service to unsubscribes from a layer from a
+     * specific publisher.
+     *
+     * This message type uses enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.
+     */
+    UNSUBSCRIBE_TO_PUBLISHER = 4,
+    /**
+     * Information from the publishers to the VMS service about the layers which the client can
+     * publish.
+     *
+     * This message type uses enum VmsOfferingMessageIntegerValuesIndex.
+     */
+    OFFERING = 5,
+    /**
+     * A request from the subscribers to the VMS service to get the available layers.
+     *
+     * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+     */
+    AVAILABILITY_REQUEST = 6,
+    /**
+     * A request from the publishers to the VMS service to get the layers with subscribers.
+     *
+     * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+     */
+    SUBSCRIPTIONS_REQUEST = 7,
+    /**
+     * A response from the VMS service to the subscribers to a VmsMessageType.AVAILABILITY_REQUEST
+     *
+     * This message type uses enum VmsAvailabilityStateIntegerValuesIndex.
+     */
+    AVAILABILITY_RESPONSE = 8,
+    /**
+     * A notification from the VMS service to the subscribers on a change in the available layers.
+     *
+     * This message type uses enum VmsAvailabilityStateIntegerValuesIndex.
+     */
+    AVAILABILITY_CHANGE = 9,
+    /**
+     * A response from the VMS service to the publishers to a VmsMessageType.SUBSCRIPTIONS_REQUEST
+     *
+     * This message type uses enum VmsSubscriptionsStateIntegerValuesIndex.
+     */
+    SUBSCRIPTIONS_RESPONSE = 10,
+    /**
+     * A notification from the VMS service to the publishers on a change in the layers with
+     * subscribers.
+     *
+     * This message type uses enum VmsSubscriptionsStateIntegerValuesIndex.
+     */
+    SUBSCRIPTIONS_CHANGE = 11,
+    /**
+     * A message from the VMS service to the subscribers or from the publishers to the VMS service
+     * with a serialized VMS data packet as defined in the VMS protocol.
+     *
+     * This message type uses enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.
+     */
+    DATA = 12,
+    /**
+     * A request from the publishers to the VMS service to get a Publisher ID for a serialized VMS
+     * provider description packet as defined in the VMS protocol.
+     *
+     * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+     */
+    PUBLISHER_ID_REQUEST = 13,
+    /**
+     * A response from the VMS service to the publisher that contains a provider description packet
+     * and the publisher ID assigned to it.
+     *
+     * This message type uses enum VmsPublisherInformationIntegerValuesIndex.
+     */
+    PUBLISHER_ID_RESPONSE = 14,
+    /**
+     * A request from the subscribers to the VMS service to get information for a Publisher ID.
+     *
+     * This message type uses enum VmsPublisherInformationIntegerValuesIndex.
+     */
+    PUBLISHER_INFORMATION_REQUEST = 15,
+    /**
+     * A response from the VMS service to the subscribers that contains a provider description
+     * packet and the publisher ID assigned to it.
+     *
+     * This message type uses enum VmsPublisherInformationIntegerValuesIndex.
+     */
+    PUBLISHER_INFORMATION_RESPONSE = 16,
+    /**
+     * A notification indicating that the sender has been reset.
+     *
+     * The receiving party must reset its internal state and respond to the
+     * sender with a START_SESSION message as acknowledgement.
+     *
+     * This message type uses enum VmsStartSessionMessageIntegerValuesIndex.
+     */
+    START_SESSION = 17,
+    // LAST_VMS_MESSAGE_TYPE = START_SESSION,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.aidl
new file mode 100644
index 0000000..c3a189c
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.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.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsMessageWithLayerIntegerValuesIndex;
+
+/*
+ * A VMS message with a layer and publisher ID is sent as part of a
+ * VmsMessageType.SUBSCRIBE_TO_PUBLISHER, VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER messages and
+ * VmsMessageType.DATA .
+ */
+@VintfStability
+@Backing(type="int")
+enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex {
+    /*
+     * The message type as enumerated by VmsMessageType enum.
+     */
+    MESSAGE_TYPE = 0,
+    LAYER_TYPE = 1,
+    LAYER_SUBTYPE = 2,
+    LAYER_VERSION = 3,
+    PUBLISHER_ID = 4,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerIntegerValuesIndex.aidl
new file mode 100644
index 0000000..b209bf6
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerIntegerValuesIndex.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/*
+ * A VMS message with a layer is sent as part of a VmsMessageType.SUBSCRIBE or
+ * VmsMessageType.UNSUBSCRIBE messages.
+ *
+ * The layer type is defined in the VMS protocol, and the subtype and version are
+ * controlled by the implementer of the publisher.
+ */
+@VintfStability
+@Backing(type="int")
+enum VmsMessageWithLayerIntegerValuesIndex {
+    /*
+     * The message type as enumerated by VmsMessageType enum.
+     */
+    MESSAGE_TYPE = 0,
+    LAYER_TYPE = 1,
+    LAYER_SUBTYPE = 2,
+    LAYER_VERSION = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsOfferingMessageIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsOfferingMessageIntegerValuesIndex.aidl
new file mode 100644
index 0000000..91c3297
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsOfferingMessageIntegerValuesIndex.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.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/*
+ * An offering can be sent by publishers as part of VmsMessageType.OFFERING in order to
+ * advertise which layers they can publish and under which constraints: e.g., I can publish Layer X
+ * if someone else will publish Layer Y.
+ * The offering contains the publisher ID which was assigned to the publisher by the VMS service.
+ * A single offering is represented as:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of dependencies (N)
+ * - N x (Layer type, Layer subtype, Layer version)
+ */
+@VintfStability
+@Backing(type="int")
+enum VmsOfferingMessageIntegerValuesIndex {
+    /*
+     * The message type as enumerated by VmsMessageType enum.
+     */
+    MESSAGE_TYPE = 0,
+    PUBLISHER_ID = 1,
+    NUMBER_OF_OFFERS = 2,
+    OFFERING_START = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsPublisherInformationIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsPublisherInformationIntegerValuesIndex.aidl
new file mode 100644
index 0000000..79bbe50
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsPublisherInformationIntegerValuesIndex.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/*
+ * Publishers send the VMS service their information and assigned in response a publisher ID.
+ * Subscribers can request the publisher information for a publisher ID they received in other
+ * messages.
+ */
+@VintfStability
+@Backing(type="int")
+enum VmsPublisherInformationIntegerValuesIndex {
+    /*
+     * The message type as enumerated by VmsMessageType enum.
+     */
+    MESSAGE_TYPE = 0,
+    PUBLISHER_ID = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsStartSessionMessageIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsStartSessionMessageIntegerValuesIndex.aidl
new file mode 100644
index 0000000..313ed89
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsStartSessionMessageIntegerValuesIndex.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/*
+ * Handshake data sent as part of a VmsMessageType.START_SESSION message.
+ *
+ * A new session is initiated by sending a START_SESSION message with the
+ * sender's identifier populated and the receiver's identifier set to -1.
+ *
+ * Identifier values are independently generated, but must be non-negative, and
+ * increase monotonically between reboots.
+ *
+ * Upon receiving a START_SESSION with a mis-matching identifier, the receiver
+ * must clear any cached VMS offering or subscription state and acknowledge the
+ * new session by responding with a START_SESSION message that populates both
+ * identifier fields.
+ *
+ * Any VMS messages received between initiation and completion of the handshake
+ * must be discarded.
+ */
+@VintfStability
+@Backing(type="int")
+enum VmsStartSessionMessageIntegerValuesIndex {
+    /*
+     * The message type as enumerated by VmsMessageType enum.
+     */
+    MESSAGE_TYPE = 0,
+    /*
+     * Identifier field for the Android system service.
+     */
+    SERVICE_ID = 1,
+    /*
+     * Identifier field for the HAL client process.
+     */
+    CLIENT_ID = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsSubscriptionsStateIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsSubscriptionsStateIntegerValuesIndex.aidl
new file mode 100644
index 0000000..cd03535
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsSubscriptionsStateIntegerValuesIndex.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/**
+ * A subscriptions state is sent to the publishers in response to a change in the subscriptions
+ * as part of a VmsMessageType.SUBSCRIPTIONS_CHANGE, or in response to a
+ * VmsMessageType.SUBSCRIPTIONS_REQUEST message as part of VmsMessageType.SUBSCRIPTIONS_RESPONSE.
+ * The VMS service issues monotonically increasing sequence numbers, and in case a subscriber
+ * receives a smaller sequence number it should ignore the message. The subscriptions are sent as a
+ * list of layers followed by a list of associated layers: {Sequence number, N, M, N x layer, M x
+ * associated layer} A subscribed layer is represented as three integers:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * A subscribed associated layer is a layer with a list of publisher IDs. It is represented as:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of publisher IDs (N)
+ * - N x publisher ID
+ */
+@VintfStability
+@Backing(type="int")
+enum VmsSubscriptionsStateIntegerValuesIndex {
+    /*
+     * The message type as enumerated by VmsMessageType enum.
+     */
+    MESSAGE_TYPE = 0,
+    SEQUENCE_NUMBER = 1,
+    NUMBER_OF_LAYERS = 2,
+    NUMBER_OF_ASSOCIATED_LAYERS = 3,
+    SUBSCRIPTIONS_START = 4,
+}
diff --git a/automotive/vehicle/aidl/impl/Android.bp b/automotive/vehicle/aidl/impl/Android.bp
new file mode 100644
index 0000000..94f590d
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_defaults {
+    name: "VehicleHalDefaults",
+    static_libs: [
+        "android.hardware.automotive.vehicle-V1-ndk",
+        "libmath",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libutils",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+}
diff --git a/automotive/vehicle/aidl/impl/default_config/Android.bp b/automotive/vehicle/aidl/impl/default_config/Android.bp
new file mode 100644
index 0000000..0feaf23
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/Android.bp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library_headers {
+    name: "VehicleHalDefaultConfig",
+    vendor: true,
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    defaults: ["VehicleHalDefaults"],
+    static_libs: ["VehicleHalUtils"],
+    header_libs: ["VehicleHalTestUtilHeaders"],
+    export_static_lib_headers: ["VehicleHalUtils"],
+    export_header_lib_headers: ["VehicleHalTestUtilHeaders"],
+}
diff --git a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
new file mode 100644
index 0000000..d2b69af
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
@@ -0,0 +1,1196 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_default_config_include_DefaultConfig_H_
+#define android_hardware_automotive_vehicle_aidl_impl_default_config_include_DefaultConfig_H_
+
+#include <PropertyUtils.h>
+#include <TestPropertyUtils.h>
+#include <VehicleHalTypes.h>
+
+#include <map>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// Types used in configs, not to be exposed as public API.
+namespace defaultconfig_impl {
+
+using ::aidl::android::hardware::automotive::vehicle::EvConnectorType;
+using ::aidl::android::hardware::automotive::vehicle::EvsServiceState;
+using ::aidl::android::hardware::automotive::vehicle::EvsServiceType;
+using ::aidl::android::hardware::automotive::vehicle::FuelType;
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
+using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
+using ::aidl::android::hardware::automotive::vehicle::VehicleGear;
+using ::aidl::android::hardware::automotive::vehicle::VehicleHvacFanDirection;
+using ::aidl::android::hardware::automotive::vehicle::VehicleIgnitionState;
+using ::aidl::android::hardware::automotive::vehicle::VehicleOilLevel;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
+using ::aidl::android::hardware::automotive::vehicle::VehicleSeatOccupancyState;
+using ::aidl::android::hardware::automotive::vehicle::VehicleTurnSignal;
+using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
+using ::aidl::android::hardware::automotive::vehicle::VehicleVendorPermission;
+
+struct ConfigDeclaration {
+    VehiclePropConfig config;
+
+    // This value will be used as an initial value for the property. If this field is specified for
+    // property that supports multiple areas then it will be used for all areas unless particular
+    // area is overridden in initialAreaValue field.
+    RawPropValues initialValue;
+    // Use initialAreaValues if it is necessary to specify different values per each area.
+    std::map<int32_t, RawPropValues> initialAreaValues;
+};
+
+const std::vector<ConfigDeclaration> kVehicleProperties = {
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.floatValues = {15000.0f}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_FUEL_TYPE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.int32Values = {toInt(FuelType::FUEL_TYPE_UNLEADED)}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_EV_BATTERY_CAPACITY),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.floatValues = {150000.0f}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_EV_CONNECTOR_TYPE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.int32Values = {toInt(EvConnectorType::IEC_TYPE_1_AC)}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_FUEL_DOOR_LOCATION),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.int32Values = {FUEL_DOOR_REAR_LEFT}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_EV_PORT_LOCATION),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.int32Values = {CHARGE_PORT_FRONT_LEFT}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_MULTI_EV_PORT_LOCATIONS),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.int32Values = {CHARGE_PORT_FRONT_LEFT, CHARGE_PORT_REAR_LEFT}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_MAKE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.stringValue = "Toy Vehicle"}},
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_MODEL),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.stringValue = "Speedy Model"}},
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_MODEL_YEAR),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.int32Values = {2020}}},
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_EXTERIOR_DIMENSIONS),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.int32Values = {1776, 4950, 2008, 2140, 2984, 1665, 1667, 11800}}},
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 10.0f,
+                 },
+         .initialValue = {.floatValues = {0.0f}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::VEHICLE_SPEED_DISPLAY_UNITS),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .configArray = {toInt(VehicleUnit::METER_PER_SEC),
+                                         toInt(VehicleUnit::MILES_PER_HOUR),
+                                         toInt(VehicleUnit::KILOMETERS_PER_HOUR)},
+                 },
+         .initialValue = {.int32Values = {toInt(VehicleUnit::KILOMETERS_PER_HOUR)}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::SEAT_OCCUPANCY),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .areaConfigs = {VehicleAreaConfig{.areaId = (SEAT_1_LEFT)},
+                                         VehicleAreaConfig{.areaId = (SEAT_1_RIGHT)}},
+                 },
+         .initialAreaValues = {{SEAT_1_LEFT,
+                                {.int32Values = {toInt(VehicleSeatOccupancyState::VACANT)}}},
+                               {SEAT_1_RIGHT,
+                                {.int32Values = {toInt(VehicleSeatOccupancyState::VACANT)}}}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_DRIVER_SEAT),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                         // this was a zoned property on an old vhal, but it is meant to be global
+                         .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+                 },
+         .initialValue = {.int32Values = {SEAT_1_LEFT}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::PERF_ODOMETER),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 10.0f,
+                 },
+         .initialValue = {.floatValues = {0.0f}}},
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::PERF_STEERING_ANGLE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 10.0f,
+                 },
+         .initialValue = {.floatValues = {0.0f}}},
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::PERF_REAR_STEERING_ANGLE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 10.0f,
+                 },
+         .initialValue = {.floatValues = {0.0f}}},
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::ENGINE_RPM),
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                                .minSampleRate = 1.0f,
+                                .maxSampleRate = 10.0f,
+                        },
+                .initialValue = {.floatValues = {0.0f}},
+        },
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::FUEL_LEVEL),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 100.0f,
+                 },
+         .initialValue = {.floatValues = {15000.0f}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::FUEL_DOOR_OPEN),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {0}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::EV_BATTERY_LEVEL),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 100.0f,
+                 },
+         .initialValue = {.floatValues = {150000.0f}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::EV_CHARGE_PORT_OPEN),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {0}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::EV_CHARGE_PORT_CONNECTED),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {0}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 10.0f,
+                 },
+         .initialValue = {.floatValues = {0.0f}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::RANGE_REMAINING),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 2.0f,
+                 },
+         .initialValue = {.floatValues = {50000.0f}}},  // units in meters
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::TIRE_PRESSURE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .areaConfigs = {VehicleAreaConfig{
+                                                 .areaId = WHEEL_FRONT_LEFT,
+                                                 .minFloatValue = 193.0f,
+                                                 .maxFloatValue = 300.0f,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_FRONT_RIGHT,
+                                                 .minFloatValue = 193.0f,
+                                                 .maxFloatValue = 300.0f,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_REAR_LEFT,
+                                                 .minFloatValue = 193.0f,
+                                                 .maxFloatValue = 300.0f,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_REAR_RIGHT,
+                                                 .minFloatValue = 193.0f,
+                                                 .maxFloatValue = 300.0f,
+                                         }},
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 2.0f,
+                 },
+         .initialValue = {.floatValues = {200.0f}}},  // units in kPa
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialAreaValues = {{WHEEL_FRONT_LEFT, {.floatValues = {137.0f}}},
+                               {WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}},
+                               {WHEEL_REAR_RIGHT, {.floatValues = {137.0f}}},
+                               {WHEEL_REAR_LEFT, {.floatValues = {137.0f}}}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::TIRE_PRESSURE_DISPLAY_UNITS),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .configArray = {toInt(VehicleUnit::KILOPASCAL), toInt(VehicleUnit::PSI),
+                                         toInt(VehicleUnit::BAR)},
+                 },
+         .initialValue = {.int32Values = {toInt(VehicleUnit::PSI)}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::CURRENT_GEAR),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .configArray = {toInt(VehicleGear::GEAR_PARK),
+                                         toInt(VehicleGear::GEAR_NEUTRAL),
+                                         toInt(VehicleGear::GEAR_REVERSE),
+                                         toInt(VehicleGear::GEAR_1), toInt(VehicleGear::GEAR_2),
+                                         toInt(VehicleGear::GEAR_3), toInt(VehicleGear::GEAR_4),
+                                         toInt(VehicleGear::GEAR_5)},
+                 },
+         .initialValue = {.int32Values = {toInt(VehicleGear::GEAR_PARK)}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::PARKING_BRAKE_ON),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {1}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::PARKING_BRAKE_AUTO_APPLY),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {1}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::FUEL_LEVEL_LOW),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {0}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::HW_KEY_INPUT),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {0, 0, 0}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::HW_ROTARY_INPUT),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {0, 0, 0}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::HW_CUSTOM_INPUT),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .configArray = {0, 0, 0, 3, 0, 0, 0, 0, 0},
+                 },
+         .initialValue =
+                 {
+                         .int32Values = {0, 0, 0},
+                 }},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_POWER_ON),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}},
+                    // TODO(bryaneyler): Ideally, this is generated dynamically from
+                    // kHvacPowerProperties.
+                    .configArray = {toInt(VehicleProperty::HVAC_FAN_SPEED),
+                                    toInt(VehicleProperty::HVAC_FAN_DIRECTION)}},
+         .initialValue = {.int32Values = {1}}},
+
+        {
+                .config = {.prop = toInt(VehicleProperty::HVAC_DEFROSTER),
+                           .access = VehiclePropertyAccess::READ_WRITE,
+                           .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                           .areaConfigs =
+                                   {VehicleAreaConfig{
+                                            .areaId = toInt(VehicleAreaWindow::FRONT_WINDSHIELD)},
+                                    VehicleAreaConfig{
+                                            .areaId = toInt(VehicleAreaWindow::REAR_WINDSHIELD)}}},
+                .initialValue = {.int32Values = {0}}  // Will be used for all areas.
+        },
+        {
+                .config = {.prop = toInt(VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON),
+                           .access = VehiclePropertyAccess::READ_WRITE,
+                           .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                           .areaConfigs =
+                                   {VehicleAreaConfig{
+                                            .areaId = toInt(VehicleAreaWindow::FRONT_WINDSHIELD)},
+                                    VehicleAreaConfig{
+                                            .areaId = toInt(VehicleAreaWindow::REAR_WINDSHIELD)}}},
+                .initialValue = {.int32Values = {0}}  // Will be used for all areas.
+        },
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_MAX_DEFROST_ON),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_RECIRC_ON),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+         .initialValue = {.int32Values = {1}}},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_AUTO_RECIRC_ON),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_AC_ON),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+         .initialValue = {.int32Values = {1}}},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_MAX_AC_ON),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_AUTO_ON),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+         .initialValue = {.int32Values = {1}}},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_DUAL_ON),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{
+                            .areaId = HVAC_ALL, .minInt32Value = 1, .maxInt32Value = 7}}},
+         .initialValue = {.int32Values = {3}}},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+         .initialValue = {.int32Values = {toInt(VehicleHvacFanDirection::FACE)}}},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION_AVAILABLE),
+                    .access = VehiclePropertyAccess::READ,
+                    .changeMode = VehiclePropertyChangeMode::STATIC,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+         .initialValue = {.int32Values = {FAN_DIRECTION_FACE, FAN_DIRECTION_FLOOR,
+                                          FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR,
+                                          FAN_DIRECTION_DEFROST,
+                                          FAN_DIRECTION_FACE | FAN_DIRECTION_DEFROST,
+                                          FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST,
+                                          FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST |
+                                                  FAN_DIRECTION_FACE}}},
+        {.config = {.prop = toInt(VehicleProperty::HVAC_SEAT_VENTILATION),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{
+                                            .areaId = SEAT_1_LEFT,
+                                            .minInt32Value = 0,
+                                            .maxInt32Value = 3,
+                                    },
+                                    VehicleAreaConfig{
+                                            .areaId = SEAT_1_RIGHT,
+                                            .minInt32Value = 0,
+                                            .maxInt32Value = 3,
+                                    }}},
+         .initialValue =
+                 {.int32Values = {0}}},  // 0 is off and +ve values indicate ventilation level.
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_STEERING_WHEEL_HEAT),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{
+                            .areaId = (0), .minInt32Value = -2, .maxInt32Value = 2}}},
+         .initialValue = {.int32Values = {0}}},  // +ve values for heating and -ve for cooling
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{
+                                            .areaId = SEAT_1_LEFT,
+                                            .minInt32Value = -2,
+                                            .maxInt32Value = 2,
+                                    },
+                                    VehicleAreaConfig{
+                                            .areaId = SEAT_1_RIGHT,
+                                            .minInt32Value = -2,
+                                            .maxInt32Value = 2,
+                                    }}},
+         .initialValue = {.int32Values = {0}}},  // +ve values for heating and -ve for cooling
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .configArray = {160, 280, 5, 605, 825, 10},
+                    .areaConfigs = {VehicleAreaConfig{
+                                            .areaId = HVAC_LEFT,
+                                            .minFloatValue = 16,
+                                            .maxFloatValue = 32,
+                                    },
+                                    VehicleAreaConfig{
+                                            .areaId = HVAC_RIGHT,
+                                            .minFloatValue = 16,
+                                            .maxFloatValue = 32,
+                                    }}},
+         .initialAreaValues = {{HVAC_LEFT, {.floatValues = {16}}},
+                               {HVAC_RIGHT, {.floatValues = {20}}}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.floatValues = {66.2f, (float)VehicleUnit::FAHRENHEIT, 19.0f, 66.5f}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE),
+                         .access = VehiclePropertyAccess::READ,
+                         // TODO(bryaneyler): Support ON_CHANGE as well.
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 2.0f,
+                 },
+         .initialValue = {.floatValues = {25.0f}}},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_DISPLAY_UNITS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .configArray = {toInt(VehicleUnit::FAHRENHEIT), toInt(VehicleUnit::CELSIUS)}},
+         .initialValue = {.int32Values = {toInt(VehicleUnit::FAHRENHEIT)}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::DISTANCE_DISPLAY_UNITS),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+                         .configArray = {toInt(VehicleUnit::KILOMETER), toInt(VehicleUnit::MILE)},
+                 },
+         .initialValue = {.int32Values = {toInt(VehicleUnit::MILE)}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::NIGHT_MODE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {0}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::GEAR_SELECTION),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .configArray = {toInt(VehicleGear::GEAR_PARK),
+                                         toInt(VehicleGear::GEAR_NEUTRAL),
+                                         toInt(VehicleGear::GEAR_REVERSE),
+                                         toInt(VehicleGear::GEAR_DRIVE), toInt(VehicleGear::GEAR_1),
+                                         toInt(VehicleGear::GEAR_2), toInt(VehicleGear::GEAR_3),
+                                         toInt(VehicleGear::GEAR_4), toInt(VehicleGear::GEAR_5)},
+                 },
+         .initialValue = {.int32Values = {toInt(VehicleGear::GEAR_PARK)}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::TURN_SIGNAL_STATE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {toInt(VehicleTurnSignal::NONE)}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::IGNITION_STATE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {toInt(VehicleIgnitionState::ON)}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::ENGINE_OIL_LEVEL),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {toInt(VehicleOilLevel::NORMAL)}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::ENGINE_OIL_TEMP),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .minSampleRate = 0.1,  // 0.1 Hz, every 10 seconds
+                         .maxSampleRate = 10,   // 10 Hz, every 100 ms
+                 },
+         .initialValue = {.floatValues = {101.0f}}},
+
+        {
+                .config = {.prop = kMixedTypePropertyForTest,
+                           .access = VehiclePropertyAccess::READ_WRITE,
+                           .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                           .configArray = {1, 1, 0, 2, 0, 0, 1, 0, 0}},
+                .initialValue =
+                        {
+                                .int32Values = {1 /* indicate TRUE boolean value */, 2, 3},
+                                .floatValues = {4.5f},
+                                .stringValue = "MIXED property",
+                        },
+        },
+
+        {.config = {.prop = toInt(VehicleProperty::DOOR_LOCK),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = DOOR_1_LEFT},
+                                    VehicleAreaConfig{.areaId = DOOR_1_RIGHT},
+                                    VehicleAreaConfig{.areaId = DOOR_2_LEFT},
+                                    VehicleAreaConfig{.areaId = DOOR_2_RIGHT}}},
+         .initialAreaValues = {{DOOR_1_LEFT, {.int32Values = {1}}},
+                               {DOOR_1_RIGHT, {.int32Values = {1}}},
+                               {DOOR_2_LEFT, {.int32Values = {1}}},
+                               {DOOR_2_RIGHT, {.int32Values = {1}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::DOOR_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs =
+                            {VehicleAreaConfig{
+                                     .areaId = DOOR_1_LEFT, .minInt32Value = 0, .maxInt32Value = 1},
+                             VehicleAreaConfig{.areaId = DOOR_1_RIGHT,
+                                               .minInt32Value = 0,
+                                               .maxInt32Value = 1},
+                             VehicleAreaConfig{
+                                     .areaId = DOOR_2_LEFT, .minInt32Value = 0, .maxInt32Value = 1},
+                             VehicleAreaConfig{.areaId = DOOR_2_RIGHT,
+                                               .minInt32Value = 0,
+                                               .maxInt32Value = 1},
+                             VehicleAreaConfig{
+                                     .areaId = DOOR_REAR, .minInt32Value = 0, .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::WINDOW_LOCK),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = WINDOW_1_RIGHT | WINDOW_2_LEFT |
+                                                                WINDOW_2_RIGHT}}},
+         .initialAreaValues = {{WINDOW_1_RIGHT | WINDOW_2_LEFT | WINDOW_2_RIGHT,
+                                {.int32Values = {0}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::WINDOW_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = WINDOW_1_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = WINDOW_1_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = WINDOW_2_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = WINDOW_2_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = WINDOW_ROOF_TOP_1,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config =
+                 {
+                         .prop = WHEEL_TICK,
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .configArray = {ALL_WHEELS, 50000, 50000, 50000, 50000},
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 10.0f,
+                 },
+         .initialValue = {.int64Values = {0, 100000, 200000, 300000, 400000}}},
+
+        {.config = {.prop = ABS_ACTIVE,
+                    .access = VehiclePropertyAccess::READ,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = TRACTION_CONTROL_ACTIVE,
+                    .access = VehiclePropertyAccess::READ,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+                    .access = VehiclePropertyAccess::READ,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .configArray = {3}},
+         .initialValue = {.int32Values = {toInt(VehicleApPowerStateReq::ON), 0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+         .initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL), 0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.minInt32Value = 0, .maxInt32Value = 100}}},
+         .initialValue = {.int32Values = {100}}},
+
+        {
+                .config = {.prop = OBD2_LIVE_FRAME,
+                           .access = VehiclePropertyAccess::READ,
+                           .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                           .configArray = {0, 0}},
+        },
+
+        {
+                .config = {.prop = OBD2_FREEZE_FRAME,
+                           .access = VehiclePropertyAccess::READ,
+                           .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                           .configArray = {0, 0}},
+        },
+
+        {
+                .config = {.prop = OBD2_FREEZE_FRAME_INFO,
+                           .access = VehiclePropertyAccess::READ,
+                           .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+        },
+
+        {
+                .config = {.prop = OBD2_FREEZE_FRAME_CLEAR,
+                           .access = VehiclePropertyAccess::WRITE,
+                           .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                           .configArray = {1}},
+        },
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::HEADLIGHTS_STATE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::HIGH_BEAM_LIGHTS_STATE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::FOG_LIGHTS_STATE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::HAZARD_LIGHTS_STATE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::HEADLIGHTS_SWITCH),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::HIGH_BEAM_LIGHTS_SWITCH),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::FOG_LIGHTS_SWITCH),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::HAZARD_LIGHTS_SWITCH),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::EVS_SERVICE_REQUEST),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {toInt(EvsServiceType::REARVIEW),
+                                          toInt(EvsServiceState::OFF)}}},
+
+        {.config = {.prop = VEHICLE_MAP_SERVICE,
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE}},
+
+        // Example Vendor Extension properties for testing
+        {.config = {.prop = VENDOR_EXTENSION_BOOLEAN_PROPERTY,
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = DOOR_1_LEFT},
+                                    VehicleAreaConfig{.areaId = DOOR_1_RIGHT},
+                                    VehicleAreaConfig{.areaId = DOOR_2_LEFT},
+                                    VehicleAreaConfig{.areaId = DOOR_2_RIGHT}}},
+         .initialAreaValues = {{DOOR_1_LEFT, {.int32Values = {1}}},
+                               {DOOR_1_RIGHT, {.int32Values = {1}}},
+                               {DOOR_2_LEFT, {.int32Values = {0}}},
+                               {DOOR_2_RIGHT, {.int32Values = {0}}}}},
+
+        {.config = {.prop = VENDOR_EXTENSION_FLOAT_PROPERTY,
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_LEFT,
+                                                      .minFloatValue = -10,
+                                                      .maxFloatValue = 10},
+                                    VehicleAreaConfig{.areaId = HVAC_RIGHT,
+                                                      .minFloatValue = -10,
+                                                      .maxFloatValue = 10}}},
+         .initialAreaValues = {{HVAC_LEFT, {.floatValues = {1}}},
+                               {HVAC_RIGHT, {.floatValues = {2}}}}},
+
+        {.config = {.prop = VENDOR_EXTENSION_INT_PROPERTY,
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs =
+                            {VehicleAreaConfig{.areaId = toInt(VehicleAreaWindow::FRONT_WINDSHIELD),
+                                               .minInt32Value = -100,
+                                               .maxInt32Value = 100},
+                             VehicleAreaConfig{.areaId = toInt(VehicleAreaWindow::REAR_WINDSHIELD),
+                                               .minInt32Value = -100,
+                                               .maxInt32Value = 100},
+                             VehicleAreaConfig{.areaId = toInt(VehicleAreaWindow::ROOF_TOP_1),
+                                               .minInt32Value = -100,
+                                               .maxInt32Value = 100}}},
+         .initialAreaValues = {{toInt(VehicleAreaWindow::FRONT_WINDSHIELD), {.int32Values = {1}}},
+                               {toInt(VehicleAreaWindow::REAR_WINDSHIELD), {.int32Values = {0}}},
+                               {toInt(VehicleAreaWindow::ROOF_TOP_1), {.int32Values = {-1}}}}},
+
+        {.config = {.prop = VENDOR_EXTENSION_STRING_PROPERTY,
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+         .initialValue = {.stringValue = "Vendor String Property"}},
+
+        {.config = {.prop = toInt(VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_TYPE),
+                    .access = VehiclePropertyAccess::READ,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_STATUS),
+                    .access = VehiclePropertyAccess::READ,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::SUPPORT_CUSTOMIZE_VENDOR_PERMISSION),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .configArray = {kMixedTypePropertyForTest,
+                                         toInt(VehicleVendorPermission::
+                                                       PERMISSION_GET_VENDOR_CATEGORY_INFO),
+                                         toInt(VehicleVendorPermission::
+                                                       PERMISSION_SET_VENDOR_CATEGORY_INFO),
+                                         VENDOR_EXTENSION_INT_PROPERTY,
+                                         toInt(VehicleVendorPermission::
+                                                       PERMISSION_GET_VENDOR_CATEGORY_SEAT),
+                                         toInt(VehicleVendorPermission::PERMISSION_NOT_ACCESSIBLE),
+                                         VENDOR_EXTENSION_FLOAT_PROPERTY,
+                                         toInt(VehicleVendorPermission::PERMISSION_DEFAULT),
+                                         toInt(VehicleVendorPermission::PERMISSION_DEFAULT)},
+                 },
+         .initialValue = {.int32Values = {1}}},
+
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::SWITCH_USER),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CREATE_USER),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::REMOVE_USER),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::POWER_POLICY_REQ),
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::POWER_POLICY_GROUP_REQ),
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CURRENT_POWER_POLICY),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::ANDROID_EPOCH_TIME),
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::WATCHDOG_ALIVE),
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::WATCHDOG_TERMINATED_PROCESS),
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::VHAL_HEARTBEAT),
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CLUSTER_SWITCH_UI),
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {0 /* ClusterHome */}},
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CLUSTER_DISPLAY_STATE),
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1,
+                                                 -1, -1 /* Insets */}},
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CLUSTER_REPORT_STATE),
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                                .configArray = {0, 0, 0, 11, 0, 0, 0, 0, 16},
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY),
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE),
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_INT,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {0}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_FLOAT,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.floatValues = {0.0f}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_BOOLEAN,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {0 /* false */}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_STRING,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.stringValue = {"Test"}},
+        },
+#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+        // Vendor propetry for E2E ClusterHomeService testing.
+        {
+                .config =
+                        {
+                                .prop = VENDOR_CLUSTER_SWITCH_UI,
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = VENDOR_CLUSTER_DISPLAY_STATE,
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = VENDOR_CLUSTER_REPORT_STATE,
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                                .configArray = {0, 0, 0, 11, 0, 0, 0, 0, 16},
+                        },
+                .initialValue = {.int32Values = {0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1,
+                                                 -1, -1 /* Insets */, 0 /* ClusterHome */,
+                                                 -1 /* ClusterNone */}},
+        },
+        {
+                .config =
+                        {
+                                .prop = VENDOR_CLUSTER_REQUEST_DISPLAY,
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {0 /* ClusterHome */}},
+        },
+        {
+                .config =
+                        {
+                                .prop = VENDOR_CLUSTER_NAVIGATION_STATE,
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+#endif  // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+};
+
+}  // namespace defaultconfig_impl
+
+// public namespace
+namespace defaultconfig {
+
+typedef defaultconfig_impl::ConfigDeclaration ConfigDeclaration;
+
+inline constexpr const std::vector<ConfigDeclaration>& getDefaultConfigs() {
+    return defaultconfig_impl::kVehicleProperties;
+}
+
+}  // namespace defaultconfig
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_default_config_include_DefaultConfig_H_
diff --git a/automotive/vehicle/aidl/impl/default_config/test/Android.bp b/automotive/vehicle/aidl/impl/default_config/test/Android.bp
new file mode 100644
index 0000000..771472c
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/test/Android.bp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "VehicleHalDefaultConfigTest",
+    vendor: true,
+    defaults: ["VehicleHalDefaults"],
+    srcs: ["*.cpp"],
+    static_libs: [
+        "VehicleHalUtils",
+        "libgtest",
+    ],
+    header_libs: [
+        "VehicleHalDefaultConfig",
+    ],
+    test_suites: ["device-tests"],
+}
diff --git a/automotive/vehicle/aidl/impl/default_config/test/DefaultConfigTest.cpp b/automotive/vehicle/aidl/impl/default_config/test/DefaultConfigTest.cpp
new file mode 100644
index 0000000..baaae75
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/test/DefaultConfigTest.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <DefaultConfig.h>
+#include <VehicleUtils.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace defaultconfig {
+
+namespace test {
+
+TEST(DefaultConfigTest, loadDefaultConfigs) {
+    for (ConfigDeclaration config : getDefaultConfigs()) {
+        ASSERT_NE(0, config.config.prop);
+    }
+}
+
+}  // namespace test
+
+}  // namespace defaultconfig
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/Android.bp
new file mode 100644
index 0000000..ab223d3
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/Android.bp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library {
+    name: "FakeVehicleHalValueGenerators",
+    vendor: true,
+    srcs: ["src/*.cpp"],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    defaults: ["VehicleHalDefaults"],
+    static_libs: [
+        "VehicleHalUtils",
+        "FakeObd2Frame",
+    ],
+    shared_libs: [
+        "libjsoncpp",
+    ],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h
new file mode 100644
index 0000000..93ffebf
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_FakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_FakeValueGenerator_H_
+
+#include <VehicleHalTypes.h>
+
+#include <optional>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+// A abstract class for all fake value generators.
+class FakeValueGenerator {
+  public:
+    virtual ~FakeValueGenerator() = default;
+
+    // Returns the next event if there is one or {@code std::nullopt} if there is none.
+    virtual std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+    nextEvent() = 0;
+};
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_FakeValueGenerator_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h
new file mode 100644
index 0000000..ad04d23
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_
+#define android_hardware_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_
+
+#include "FakeValueGenerator.h"
+
+#include <android-base/thread_annotations.h>
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <iostream>
+#include <mutex>
+#include <optional>
+#include <queue>
+#include <thread>
+#include <unordered_map>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+// This is the scheduler for all VHAL event generators. It manages all generators and uses priority
+// queue to maintain generated events ordered by timestamp. The scheduler uses a single thread to
+// keep querying and updating the event queue to make sure events from all generators are produced
+// in order.
+class GeneratorHub {
+  public:
+    using OnHalEvent = std::function<void(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& event)>;
+
+    explicit GeneratorHub(OnHalEvent&& onHalEvent);
+    ~GeneratorHub();
+
+    // Register a new generator. The generator will be discarded if it could not produce next event.
+    // The existing generator will be overridden if it has the same generatorId.
+    void registerGenerator(int32_t generatorId, std::unique_ptr<FakeValueGenerator> generator);
+
+    // Unregister a generator with the generatorId. If no registered generator is found, this
+    // function does nothing.
+    void unregisterGenerator(int32_t generatorId);
+
+  private:
+    struct VhalEvent {
+        int32_t generatorId;
+        ::aidl::android::hardware::automotive::vehicle::VehiclePropValue val;
+    };
+
+    // Comparator used by priority queue to keep track of soonest event.
+    struct GreaterByTime {
+        bool operator()(const VhalEvent& lhs, const VhalEvent& rhs) const {
+            return lhs.val.timestamp > rhs.val.timestamp;
+        }
+    };
+
+    std::priority_queue<VhalEvent, std::vector<VhalEvent>, GreaterByTime> mEventQueue;
+    std::mutex mGeneratorsLock;
+    std::unordered_map<int32_t, std::unique_ptr<FakeValueGenerator>> mGenerators
+            GUARDED_BY(mGeneratorsLock);
+    OnHalEvent mOnHalEvent;
+    std::condition_variable mCond;
+    std::thread mThread;
+    std::atomic<bool> mShuttingDownFlag{false};
+
+    // Main loop of the single thread to producing event and updating event queue.
+    void run();
+};
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
new file mode 100644
index 0000000..8116ed2
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_
+
+#include "FakeValueGenerator.h"
+
+#include <json/json.h>
+
+#include <iostream>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+class JsonFakeValueGenerator : public FakeValueGenerator {
+  public:
+    // Create a new JSON fake value generator. {@code request.value.stringValue} is the JSON file
+    // name. {@code request.value.int32Values[1]} if exists, is the number of iterations. If
+    // {@code int32Values} has less than 2 elements, number of iterations would be set to -1, which
+    // means iterate indefinitely.
+    explicit JsonFakeValueGenerator(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& request);
+    // Create a new JSON fake value generator using the specified JSON file path. All the events
+    // in the JSON file would be generated for number of {@code iteration}. If iteration is 0, no
+    // value would be generated. If iteration is less than 0, it would iterate indefinitely.
+    explicit JsonFakeValueGenerator(const std::string& path, int32_t iteration);
+    // Create a new JSON fake value generator using the specified JSON file path. All the events
+    // in the JSON file would be generated once.
+    explicit JsonFakeValueGenerator(const std::string& path);
+
+    ~JsonFakeValueGenerator() = default;
+
+    std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> nextEvent()
+            override;
+    const std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
+    getAllEvents();
+
+  private:
+    size_t mEventIndex = 0;
+    std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> mEvents;
+    long mLastEventTimestamp = 0;
+    int32_t mNumOfIterations = 0;
+
+    void setBit(std::vector<uint8_t>& bytes, size_t idx);
+    void init(const std::string& path, int32_t iteration);
+};
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
new file mode 100644
index 0000000..bd004f3
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_
+
+#include "FakeValueGenerator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+class LinearFakeValueGenerator : public FakeValueGenerator {
+  public:
+    // A linear value generator initialized using values in request.
+    // int32Values[1]: propId
+    // floatValues[0]: middleValue and currentValue
+    // floatValues[1]: dispersion
+    // floatValues[2]: increment
+    // int64Values[0]: interval
+    // {@code propId} must be INT32 or INT64 or FLOAT type.
+    explicit LinearFakeValueGenerator(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& request);
+    // A linear value generator in range [middleValue - dispersion, middleValue + dispersion),
+    // starts at 'currentValue' and at each 'interval', increase by 'increment' and loop back if
+    // exceeds middleValue + dispersion. {@code propId} must be INT32 or INT64 or FLOAT type.
+    explicit LinearFakeValueGenerator(int32_t propId, float middleValue, float initValue,
+                                      float dispersion, float increment, int64_t interval);
+    ~LinearFakeValueGenerator() = default;
+
+    std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> nextEvent()
+            override;
+
+  private:
+    // In every timer tick we may want to generate new value based on initial value for debug
+    // purpose. It's better to have sequential values to see if events gets delivered in order
+    // to the client.
+    struct GeneratorCfg {
+        int32_t propId;
+        float middleValue;
+        float currentValue;  //  Should be in range (middleValue +/- dispersion).
+        float dispersion;    //  Defines minimum and maximum value based on initial value.
+        float increment;     //  Value that we will be added to currentValue with each timer tick.
+        int64_t interval;
+        long lastEventTimestamp;
+    };
+
+    GeneratorCfg mGenCfg;
+
+    void initGenCfg(int32_t propId, float middleValue, float initValue, float dispersion,
+                    float increment, int64_t interval);
+};
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp
new file mode 100644
index 0000000..0c182d9
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GeneratorHub"
+
+#include "GeneratorHub.h"
+
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+using ::android::base::ScopedLockAssertion;
+
+GeneratorHub::GeneratorHub(OnHalEvent&& onHalEvent)
+    : mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {}
+
+GeneratorHub::~GeneratorHub() {
+    mShuttingDownFlag.store(true);
+    mCond.notify_all();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+void GeneratorHub::registerGenerator(int32_t id, std::unique_ptr<FakeValueGenerator> generator) {
+    {
+        std::scoped_lock<std::mutex> lockGuard(mGeneratorsLock);
+        auto maybeNextEvent = generator->nextEvent();
+        // Register only if the generator can produce at least one event.
+        if (maybeNextEvent.has_value()) {
+            // Push the next event if it is a new generator
+            if (mGenerators.find(id) == mGenerators.end()) {
+                ALOGI("%s: Registering new generator, id: %d", __func__, id);
+                mEventQueue.push({id, maybeNextEvent.value()});
+            }
+            mGenerators[id] = std::move(generator);
+            ALOGI("%s: Registered generator, id: %d", __func__, id);
+        }
+    }
+    mCond.notify_one();
+}
+
+void GeneratorHub::unregisterGenerator(int32_t id) {
+    {
+        std::scoped_lock<std::mutex> lockGuard(mGeneratorsLock);
+        mGenerators.erase(id);
+    }
+    mCond.notify_one();
+    ALOGI("%s: Unregistered generator, id: %d", __func__, id);
+}
+
+void GeneratorHub::run() {
+    while (!mShuttingDownFlag.load()) {
+        std::unique_lock<std::mutex> lock(mGeneratorsLock);
+        ScopedLockAssertion lock_assertion(mGeneratorsLock);
+        // Pop events whose generator does not exist (may be already unregistered)
+        while (!mEventQueue.empty() &&
+               mGenerators.find(mEventQueue.top().generatorId) == mGenerators.end()) {
+            mEventQueue.pop();
+        }
+        // Wait until event queue is not empty or shutting down flag is set.
+        // This would unlock mGeneratorsLock and reacquire later.
+        mCond.wait(lock, [this] { return !mEventQueue.empty() || mShuttingDownFlag.load(); });
+        if (mShuttingDownFlag.load()) {
+            break;
+        }
+
+        const VhalEvent& curEvent = mEventQueue.top();
+        long currentTime = elapsedRealtimeNano();
+        long waitTime =
+                curEvent.val.timestamp > currentTime ? curEvent.val.timestamp - currentTime : 0;
+        if (waitTime != 0) {
+            // Wait until the soonest event happen
+            if (mCond.wait_for(lock, std::chrono::nanoseconds(waitTime)) !=
+                std::cv_status::timeout) {
+                // It is possible that a new generator is registered and produced a sooner event, or
+                // current generator is unregistered, in this case the thread will re-evaluate the
+                // soonest event
+                ALOGI("Something happened while waiting");
+                continue;
+            }
+        }
+        // Now it's time to handle current event.
+        mOnHalEvent(curEvent.val);
+        // Update queue by popping current event and producing next event from the same generator
+        int32_t id = curEvent.generatorId;
+        mEventQueue.pop();
+        if (mGenerators.find(id) != mGenerators.end()) {
+            auto maybeNextEvent = mGenerators[id]->nextEvent();
+            if (maybeNextEvent.has_value()) {
+                mEventQueue.push({id, maybeNextEvent.value()});
+                continue;
+            }
+        }
+
+        ALOGI("%s: Generator ended, unregister it, id: %d", __func__, id);
+        mGenerators.erase(id);
+    }
+}
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
new file mode 100644
index 0000000..ae92797
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "JsonFakeValueGenerator"
+
+#include "JsonFakeValueGenerator.h"
+
+#include <fstream>
+#include <type_traits>
+#include <typeinfo>
+
+#include <Obd2SensorStore.h>
+#include <VehicleUtils.h>
+#include <android/binder_enums.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+bool isDiagnosticProperty(int32_t prop) {
+    return prop == toInt(VehicleProperty::OBD2_LIVE_FRAME) ||
+           prop == toInt(VehicleProperty::OBD2_FREEZE_FRAME);
+}
+
+void setBit(std::vector<uint8_t>& bytes, size_t idx) {
+    uint8_t mask = 1 << (idx % 8);
+    bytes[idx / 8] |= mask;
+}
+
+template <typename T>
+void copyJsonArray(const Json::Value& jsonArray, std::vector<T>& dest) {
+    dest.resize(jsonArray.size());
+    for (Json::Value::ArrayIndex i = 0; i < jsonArray.size(); i++) {
+        if (std::is_same<T, int32_t>::value) {
+            dest[i] = jsonArray[i].asInt();
+        } else if (std::is_same<T, int64_t>::value) {
+            dest[i] = jsonArray[i].asInt64();
+        } else if (std::is_same<T, float>::value) {
+            dest[i] = jsonArray[i].asFloat();
+        }
+    }
+}
+
+void copyMixedValueJson(const Json::Value& jsonValue, RawPropValues& dest) {
+    copyJsonArray(jsonValue["int32Values"], dest.int32Values);
+    copyJsonArray(jsonValue["int64Values"], dest.int64Values);
+    copyJsonArray(jsonValue["floatValues"], dest.floatValues);
+    dest.stringValue = jsonValue["stringValue"].asString();
+}
+
+std::vector<uint8_t> generateDiagnosticBytes(const RawPropValues& diagnosticValue) {
+    size_t lastIntegerSensorIndex = static_cast<size_t>(
+            obd2frame::Obd2SensorStore::getLastIndex<DiagnosticIntegerSensorIndex>());
+    size_t lastFloatSensorIndex = static_cast<size_t>(
+            obd2frame::Obd2SensorStore::getLastIndex<DiagnosticFloatSensorIndex>());
+
+    size_t byteSize = (lastIntegerSensorIndex + lastFloatSensorIndex + 2);
+    std::vector<uint8_t> bytes((byteSize + 7) / 8);
+
+    auto& int32Values = diagnosticValue.int32Values;
+    for (size_t i = 0; i < int32Values.size(); i++) {
+        if (int32Values[i] != 0) {
+            setBit(bytes, i);
+        }
+    }
+
+    auto& floatValues = diagnosticValue.floatValues;
+    for (size_t i = 0; i < floatValues.size(); i++) {
+        if (floatValues[i] != 0.0) {
+            setBit(bytes, i + lastIntegerSensorIndex + 1);
+        }
+    }
+    return bytes;
+}
+
+std::vector<VehiclePropValue> parseFakeValueJson(std::istream& is) {
+    std::vector<VehiclePropValue> fakeVhalEvents;
+
+    Json::CharReaderBuilder builder;
+    Json::Value rawEvents;
+    std::string errorMessage;
+    if (!Json::parseFromStream(builder, is, &rawEvents, &errorMessage)) {
+        ALOGE("%s: Failed to parse fake data JSON file. Error: %s", __func__, errorMessage.c_str());
+        return fakeVhalEvents;
+    }
+
+    for (Json::Value::ArrayIndex i = 0; i < rawEvents.size(); i++) {
+        Json::Value rawEvent = rawEvents[i];
+        if (!rawEvent.isObject()) {
+            ALOGE("%s: VHAL JSON event should be an object, %s", __func__,
+                  rawEvent.toStyledString().c_str());
+            continue;
+        }
+        if (rawEvent["prop"].empty() || rawEvent["areaId"].empty() || rawEvent["value"].empty() ||
+            rawEvent["timestamp"].empty()) {
+            ALOGE("%s: VHAL JSON event has missing fields, skip it, %s", __func__,
+                  rawEvent.toStyledString().c_str());
+            continue;
+        }
+        VehiclePropValue event = {
+                .timestamp = rawEvent["timestamp"].asInt64(),
+                .areaId = rawEvent["areaId"].asInt(),
+                .prop = rawEvent["prop"].asInt(),
+        };
+
+        Json::Value rawEventValue = rawEvent["value"];
+        auto& value = event.value;
+        int32_t count;
+        switch (getPropType(event.prop)) {
+            case VehiclePropertyType::BOOLEAN:
+            case VehiclePropertyType::INT32:
+                value.int32Values.resize(1);
+                value.int32Values[0] = rawEventValue.asInt();
+                break;
+            case VehiclePropertyType::INT64:
+                value.int64Values.resize(1);
+                value.int64Values[0] = rawEventValue.asInt64();
+                break;
+            case VehiclePropertyType::FLOAT:
+                value.floatValues.resize(1);
+                value.floatValues[0] = rawEventValue.asFloat();
+                break;
+            case VehiclePropertyType::STRING:
+                value.stringValue = rawEventValue.asString();
+                break;
+            case VehiclePropertyType::INT32_VEC:
+                value.int32Values.resize(rawEventValue.size());
+                count = 0;
+                for (auto& it : rawEventValue) {
+                    value.int32Values[count++] = it.asInt();
+                }
+                break;
+            case VehiclePropertyType::MIXED:
+                copyMixedValueJson(rawEventValue, value);
+                if (isDiagnosticProperty(event.prop)) {
+                    value.byteValues = generateDiagnosticBytes(value);
+                }
+                break;
+            default:
+                ALOGE("%s: unsupported type for property: 0x%x", __func__, event.prop);
+                continue;
+        }
+        fakeVhalEvents.push_back(event);
+    }
+    return fakeVhalEvents;
+}
+
+}  // namespace
+
+JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path) {
+    init(path, 1);
+}
+
+JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path, int32_t iteration) {
+    init(path, iteration);
+}
+
+JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) {
+    const auto& v = request.value;
+    // Iterate infinitely if iteration number is not provided
+    int32_t numOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
+
+    init(v.stringValue, numOfIterations);
+}
+
+void JsonFakeValueGenerator::init(const std::string& path, int32_t iteration) {
+    std::ifstream ifs(path);
+    if (!ifs) {
+        ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str());
+        return;
+    }
+    mEvents = parseFakeValueJson(ifs);
+    mNumOfIterations = iteration;
+}
+
+const std::vector<VehiclePropValue>& JsonFakeValueGenerator::getAllEvents() {
+    return mEvents;
+}
+
+std::optional<VehiclePropValue> JsonFakeValueGenerator::nextEvent() {
+    if (mNumOfIterations == 0 || mEvents.size() == 0) {
+        return std::nullopt;
+    }
+
+    VehiclePropValue generatedValue = mEvents[mEventIndex];
+
+    if (mLastEventTimestamp == 0) {
+        mLastEventTimestamp = elapsedRealtimeNano();
+    } else {
+        long nextEventTime = 0;
+        if (mEventIndex > 0) {
+            // All events (start from 2nd one) are supposed to happen in the future with a delay
+            // equals to the duration between previous and current event.
+            nextEventTime = mLastEventTimestamp +
+                            (mEvents[mEventIndex].timestamp - mEvents[mEventIndex - 1].timestamp);
+        } else {
+            // We are starting another iteration, immediately send the next event after 1ms.
+            nextEventTime = mLastEventTimestamp + 1000000;
+        }
+        // Prevent overflow.
+        assert(nextEventTime > mLastEventTimestamp);
+        mLastEventTimestamp = nextEventTime;
+    }
+
+    mEventIndex++;
+    if (mEventIndex == mEvents.size()) {
+        mEventIndex = 0;
+        if (mNumOfIterations > 0) {
+            mNumOfIterations--;
+        }
+    }
+
+    generatedValue.timestamp = mLastEventTimestamp;
+
+    return generatedValue;
+}
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
new file mode 100644
index 0000000..9133144
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "LinearFakeValueGenerator"
+
+#include "LinearFakeValueGenerator.h"
+
+#include <VehicleUtils.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+LinearFakeValueGenerator::LinearFakeValueGenerator(int32_t propId, float middleValue,
+                                                   float initValue, float dispersion,
+                                                   float increment, int64_t interval) {
+    initGenCfg(propId, middleValue, initValue, dispersion, increment, interval);
+}
+
+LinearFakeValueGenerator::LinearFakeValueGenerator(const VehiclePropValue& request) {
+    const auto& v = request.value;
+    initGenCfg(v.int32Values[1], v.floatValues[0], v.floatValues[0], v.floatValues[1],
+               v.floatValues[2], v.int64Values[0]);
+}
+
+void LinearFakeValueGenerator::initGenCfg(int32_t propId, float middleValue, float initValue,
+                                          float dispersion, float increment, int64_t interval) {
+    // Other types are not supported.
+    assert(getPropType(propId) == VehicleProperty::INT32 ||
+           getPropType(propId) == VehicleProperty::INT64 ||
+           getPropType(propId) == VehicleProperty::FLOAT);
+
+    if (initValue < middleValue - dispersion || initValue >= middleValue + dispersion) {
+        ALOGW("%s: invalid initValue: %f, out of range, default to %f", __func__, initValue,
+              middleValue);
+        initValue = middleValue;
+    }
+    mGenCfg = GeneratorCfg{
+            .propId = propId,
+            .middleValue = middleValue,
+            .currentValue = initValue,
+            .dispersion = dispersion,
+            .increment = increment,
+            .interval = interval,
+    };
+}
+
+std::optional<VehiclePropValue> LinearFakeValueGenerator::nextEvent() {
+    VehiclePropValue event = {
+            .prop = mGenCfg.propId,
+    };
+    auto& value = event.value;
+    switch (getPropType(event.prop)) {
+        case VehiclePropertyType::INT32:
+            value.int32Values = {static_cast<int32_t>(mGenCfg.currentValue)};
+            break;
+        case VehiclePropertyType::INT64:
+            value.int64Values = {static_cast<int64_t>(mGenCfg.currentValue)};
+            break;
+        case VehiclePropertyType::FLOAT:
+            value.floatValues = {mGenCfg.currentValue};
+            break;
+        default:
+            ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop);
+    }
+    if (mGenCfg.lastEventTimestamp == 0) {
+        mGenCfg.lastEventTimestamp = elapsedRealtimeNano();
+    } else {
+        long nextEventTime = mGenCfg.lastEventTimestamp + mGenCfg.interval;
+        // Prevent overflow.
+        assert(nextEventTime > mGenCfg.lastEventTimestamp);
+        mGenCfg.lastEventTimestamp = nextEventTime;
+    }
+    event.timestamp = mGenCfg.lastEventTimestamp;
+
+    mGenCfg.currentValue += mGenCfg.increment;
+    if (mGenCfg.currentValue >= mGenCfg.middleValue + mGenCfg.dispersion) {
+        // Wrap around, (i - d) + c - (i + d) = c - 2 * d
+        mGenCfg.currentValue = mGenCfg.currentValue - 2 * mGenCfg.dispersion;
+    }
+    return event;
+}
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
new file mode 100644
index 0000000..ac8db44
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "FakeVehicleHalValueGeneratorsTest",
+    vendor: true,
+    srcs: ["*.cpp"],
+    defaults: ["VehicleHalDefaults"],
+    static_libs: [
+        "VehicleHalUtils",
+        "FakeVehicleHalValueGenerators",
+        "FakeObd2Frame",
+    ],
+    shared_libs: [
+        "libjsoncpp",
+    ],
+    data: [
+        ":FakeVehicleHalValueGeneratorsTestFiles",
+    ],
+    test_suites: ["device-tests"],
+}
+
+filegroup {
+    name: "FakeVehicleHalValueGeneratorsTestFiles",
+    srcs: [
+        "prop.json",
+        "prop_invalid.json",
+    ],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp
new file mode 100644
index 0000000..21aa680
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <GeneratorHub.h>
+#include <JsonFakeValueGenerator.h>
+#include <LinearFakeValueGenerator.h>
+#include <VehicleUtils.h>
+#include <android-base/file.h>
+#include <android-base/thread_annotations.h>
+#include <gtest/gtest.h>
+#include <utils/SystemClock.h>
+
+#include <chrono>
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <thread>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+class FakeVehicleHalValueGeneratorsTest : public ::testing::Test {
+  protected:
+    void SetUp() override {
+        mHub = std::make_unique<GeneratorHub>(
+                [this](const VehiclePropValue& event) { return onHalEvent(event); });
+    }
+
+    GeneratorHub* getHub() { return mHub.get(); }
+
+    std::vector<VehiclePropValue> getEvents() {
+        std::scoped_lock<std::mutex> lockGuard(mEventsLock);
+        return mEvents;
+    }
+
+    void clearEvents() {
+        std::scoped_lock<std::mutex> lockGuard(mEventsLock);
+        mEvents.clear();
+    }
+
+    void TearDown() override {
+        // Generator callback uses mEvents, must stop generator before destroying mEvents.
+        mHub.reset();
+    }
+
+    static std::string getTestFilePath(const char* filename) {
+        static std::string baseDir = android::base::GetExecutableDirectory();
+        return baseDir + "/" + filename;
+    }
+
+  private:
+    void onHalEvent(const VehiclePropValue& event) {
+        VehiclePropValue eventCopy = event;
+        std::scoped_lock<std::mutex> lockGuard(mEventsLock);
+        mEvents.push_back(std::move(eventCopy));
+    }
+
+    std::unique_ptr<GeneratorHub> mHub;
+    std::mutex mEventsLock;
+    std::vector<VehiclePropValue> mEvents GUARDED_BY(mEventsLock);
+};
+
+class TestFakeValueGenerator : public FakeValueGenerator {
+  public:
+    void setEvents(const std::vector<VehiclePropValue>& events) {
+        mEvents = events;
+        mEventIndex = 0;
+    }
+
+    std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> nextEvent()
+            override {
+        if (mEventIndex == mEvents.size()) {
+            return std::nullopt;
+        }
+        return mEvents[mEventIndex++];
+    }
+
+  private:
+    std::vector<VehiclePropValue> mEvents;
+    size_t mEventIndex = 0;
+};
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testRegisterTestFakeValueGenerator) {
+    auto generator = std::make_unique<TestFakeValueGenerator>();
+    std::vector<VehiclePropValue> events;
+    size_t eventCount = 10;
+    int64_t timestamp = elapsedRealtimeNano();
+    for (size_t i = 0; i < eventCount; i++) {
+        events.push_back(VehiclePropValue{
+                .prop = static_cast<int32_t>(i),
+                .timestamp = timestamp + static_cast<int64_t>(50 * i),
+        });
+    }
+    generator->setEvents(events);
+
+    getHub()->registerGenerator(0, std::move(generator));
+
+    // All the events require 500ms to generate, so waiting for 1000ms should be enough.
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+
+    ASSERT_EQ(getEvents(), events);
+
+    getHub()->unregisterGenerator(0);
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testUnregisterGeneratorStopGeneration) {
+    auto generator = std::make_unique<TestFakeValueGenerator>();
+    std::vector<VehiclePropValue> events;
+    size_t eventCount = 10;
+    int64_t timestamp = elapsedRealtimeNano();
+    for (size_t i = 0; i < eventCount; i++) {
+        events.push_back(VehiclePropValue{
+                .prop = static_cast<int32_t>(i),
+                .timestamp = timestamp + static_cast<int64_t>(50 * i),
+        });
+    }
+    generator->setEvents(events);
+
+    getHub()->registerGenerator(0, std::move(generator));
+    getHub()->unregisterGenerator(0);
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+
+    ASSERT_LT(getEvents().size(), static_cast<size_t>(10))
+            << "Must stop generating event after generator is unregistered";
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorFloat) {
+    std::unique_ptr<LinearFakeValueGenerator> generator =
+            std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+                                                       /*middleValue=*/50.0,
+                                                       /*initValue=*/30.0,
+                                                       /*dispersion=*/50.0,
+                                                       /*increment=*/20.0,
+                                                       /*interval=*/10000000);
+    getHub()->registerGenerator(0, std::move(generator));
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    auto events = getEvents();
+    // We should get 10 events ideally, but let's be safe here.
+    ASSERT_LE((size_t)5, events.size());
+    int value = 30;
+    for (size_t i = 0; i < 5; i++) {
+        EXPECT_EQ(std::vector<float>({static_cast<float>(value)}), events[i].value.floatValues);
+        value = (value + 20) % 100;
+    }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInt32) {
+    std::unique_ptr<LinearFakeValueGenerator> generator =
+            std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::INFO_MODEL_YEAR),
+                                                       /*middleValue=*/50.0,
+                                                       /*initValue=*/30.0,
+                                                       /*dispersion=*/50.0,
+                                                       /*increment=*/20.0,
+                                                       /*interval=*/10000000);
+    getHub()->registerGenerator(0, std::move(generator));
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    auto events = getEvents();
+    // We should get 10 events ideally, but let's be safe here.
+    ASSERT_LE((size_t)5, events.size());
+    int value = 30;
+    for (size_t i = 0; i < 5; i++) {
+        EXPECT_EQ(std::vector<int32_t>({value}), events[i].value.int32Values);
+        value = (value + 20) % 100;
+    }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInt64) {
+    std::unique_ptr<LinearFakeValueGenerator> generator =
+            std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::ANDROID_EPOCH_TIME),
+                                                       /*middleValue=*/50.0,
+                                                       /*initValue=*/30.0,
+                                                       /*dispersion=*/50.0,
+                                                       /*increment=*/20.0,
+                                                       /*interval=*/10000000);
+    getHub()->registerGenerator(0, std::move(generator));
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    auto events = getEvents();
+    // We should get 10 events ideally, but let's be safe here.
+    ASSERT_LE((size_t)5, events.size());
+    int value = 30;
+    for (size_t i = 0; i < 5; i++) {
+        EXPECT_EQ(std::vector<int64_t>({value}), events[i].value.int64Values);
+        value = (value + 20) % 100;
+    }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorUsingRequest) {
+    VehiclePropValue request;
+    request.value.int32Values = {0, toInt(VehicleProperty::PERF_VEHICLE_SPEED)};
+    request.value.floatValues = {/*middleValue=*/50.0, /*dispersion=*/50.0, /*increment=*/20.0};
+    request.value.int64Values = {/*interval=*/10000000};
+
+    std::unique_ptr<LinearFakeValueGenerator> generator =
+            std::make_unique<LinearFakeValueGenerator>(request);
+    getHub()->registerGenerator(0, std::move(generator));
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    auto events = getEvents();
+    // We should get 10 events ideally, but let's be safe here.
+    ASSERT_LE((size_t)5, events.size());
+    int value = 50;
+    for (size_t i = 0; i < 5; i++) {
+        EXPECT_EQ(std::vector<float>({static_cast<float>(value)}), events[i].value.floatValues);
+        value = (value + 20) % 100;
+    }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInvalidInitValue) {
+    std::unique_ptr<LinearFakeValueGenerator> generator =
+            std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+                                                       /*middleValue=*/50.0,
+                                                       // Out of range
+                                                       /*initValue=*/110.0,
+                                                       /*dispersion=*/50.0,
+                                                       /*increment=*/20.0,
+                                                       /*interval=*/10000000);
+    getHub()->registerGenerator(0, std::move(generator));
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    auto events = getEvents();
+    // We should get 10 events ideally, but let's be safe here.
+    ASSERT_LE((size_t)5, events.size());
+
+    // Init value would be set to middleValue if given initValue is not valid.
+    int value = 50;
+    for (size_t i = 0; i < 5; i++) {
+        EXPECT_EQ(std::vector<float>({static_cast<float>(value)}), events[i].value.floatValues);
+        value = (value + 20) % 100;
+    }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGenerator) {
+    long currentTime = elapsedRealtimeNano();
+
+    std::unique_ptr<JsonFakeValueGenerator> generator =
+            std::make_unique<JsonFakeValueGenerator>(getTestFilePath("prop.json"), 2);
+    getHub()->registerGenerator(0, std::move(generator));
+
+    // wait for some time.
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    std::vector<VehiclePropValue> expectedValues = {
+            VehiclePropValue{
+                    .areaId = 0,
+                    .value.int32Values = {8},
+                    .prop = 289408000,
+            },
+            VehiclePropValue{
+                    .areaId = 0,
+                    .value.int32Values = {4},
+                    .prop = 289408000,
+            },
+            VehiclePropValue{
+                    .areaId = 0,
+                    .value.int32Values = {16},
+                    .prop = 289408000,
+            },
+            VehiclePropValue{
+                    .areaId = 0,
+                    .value.int32Values = {10},
+                    .prop = 289408000,
+            },
+    };
+
+    // We have two iterations.
+    for (size_t i = 0; i < 4; i++) {
+        expectedValues.push_back(expectedValues[i]);
+    }
+
+    auto events = getEvents();
+
+    long lastEventTime = currentTime;
+    for (auto& event : events) {
+        EXPECT_GT(event.timestamp, lastEventTime);
+        lastEventTime = event.timestamp;
+        event.timestamp = 0;
+    }
+
+    EXPECT_EQ(events, expectedValues);
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorIterateIndefinitely) {
+    std::unique_ptr<JsonFakeValueGenerator> generator =
+            std::make_unique<JsonFakeValueGenerator>(getTestFilePath("prop.json"), -1);
+    getHub()->registerGenerator(0, std::move(generator));
+
+    // wait for some time.
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    auto events = getEvents();
+
+    // Send 1 iteration takes 4ms + 1ms interval between iteration, so for 100ms we should get about
+    // 20 iteration, which is 80 events.
+    EXPECT_GT(events.size(), static_cast<size_t>(50));
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorUsingRequest) {
+    long currentTime = elapsedRealtimeNano();
+
+    VehiclePropValue request = {.value = {
+                                        .stringValue = getTestFilePath("prop.json"),
+                                        .int32Values = {0, 2},
+                                }};
+
+    std::unique_ptr<JsonFakeValueGenerator> generator =
+            std::make_unique<JsonFakeValueGenerator>(request);
+    getHub()->registerGenerator(0, std::move(generator));
+
+    // wait for some time.
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    std::vector<VehiclePropValue> expectedValues = {
+            VehiclePropValue{
+                    .areaId = 0,
+                    .value.int32Values = {8},
+                    .prop = 289408000,
+            },
+            VehiclePropValue{
+                    .areaId = 0,
+                    .value.int32Values = {4},
+                    .prop = 289408000,
+            },
+            VehiclePropValue{
+                    .areaId = 0,
+                    .value.int32Values = {16},
+                    .prop = 289408000,
+            },
+            VehiclePropValue{
+                    .areaId = 0,
+                    .value.int32Values = {10},
+                    .prop = 289408000,
+            },
+    };
+
+    // We have two iterations.
+    for (size_t i = 0; i < 4; i++) {
+        expectedValues.push_back(expectedValues[i]);
+    }
+
+    auto events = getEvents();
+
+    long lastEventTime = currentTime;
+    for (auto& event : events) {
+        EXPECT_GT(event.timestamp, lastEventTime);
+        lastEventTime = event.timestamp;
+        event.timestamp = 0;
+    }
+
+    EXPECT_EQ(events, expectedValues);
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorInvalidFile) {
+    VehiclePropValue request = {.value = {
+                                        .stringValue = getTestFilePath("prop_invalid.json"),
+                                        .int32Values = {0, 2},
+                                }};
+
+    std::unique_ptr<JsonFakeValueGenerator> generator =
+            std::make_unique<JsonFakeValueGenerator>(request);
+    getHub()->registerGenerator(0, std::move(generator));
+
+    // wait for some time.
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    ASSERT_TRUE(getEvents().empty());
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorNonExistingFile) {
+    VehiclePropValue request = {.value = {
+                                        .stringValue = "non_existing_file",
+                                        .int32Values = {0, 2},
+                                }};
+
+    std::unique_ptr<JsonFakeValueGenerator> generator =
+            std::make_unique<JsonFakeValueGenerator>(request);
+    getHub()->registerGenerator(0, std::move(generator));
+
+    // wait for some time.
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    ASSERT_TRUE(getEvents().empty());
+}
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json
new file mode 100644
index 0000000..b881109
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json
@@ -0,0 +1,26 @@
+[
+  {
+    "timestamp": 1000000,
+    "areaId": 0,
+    "value": 8,
+    "prop": 289408000
+  },
+  {
+    "timestamp": 2000000,
+    "areaId": 0,
+    "value": 4,
+    "prop": 289408000
+  },
+  {
+    "timestamp": 3000000,
+    "areaId": 0,
+    "value": 16,
+    "prop": 289408000
+  },
+  {
+    "timestamp": 4000000,
+    "areaId": 0,
+    "value": 10,
+    "prop": 289408000
+  }
+]
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json
new file mode 100644
index 0000000..98232c6
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json
@@ -0,0 +1 @@
+{
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
new file mode 100644
index 0000000..dcd9208
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library {
+    name: "FakeVehicleHardware",
+    vendor: true,
+    srcs: ["src/*.cpp"],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    defaults: [
+        "VehicleHalDefaults",
+        "FakeVehicleHardwareDefaults",
+    ],
+}
+
+cc_defaults {
+    name: "FakeVehicleHardwareDefaults",
+    cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
+    header_libs: [
+        "IVehicleHardware",
+        "VehicleHalDefaultConfig",
+    ],
+    export_header_lib_headers: ["IVehicleHardware"],
+    static_libs: [
+        "VehicleHalUtils",
+        "FakeVehicleHalValueGenerators",
+        "FakeObd2Frame",
+        "FakeUserHal",
+    ],
+    shared_libs: [
+        "libjsoncpp",
+    ],
+    export_static_lib_headers: ["VehicleHalUtils"],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
new file mode 100644
index 0000000..cab184b
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_
+
+#include <DefaultConfig.h>
+#include <FakeObd2Frame.h>
+#include <FakeUserHal.h>
+#include <IVehicleHardware.h>
+#include <VehicleHalTypes.h>
+#include <VehiclePropertyStore.h>
+#include <android-base/result.h>
+#include <android-base/thread_annotations.h>
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+class FakeVehicleHardware final : public IVehicleHardware {
+  public:
+    FakeVehicleHardware();
+
+    explicit FakeVehicleHardware(std::unique_ptr<VehiclePropValuePool> valuePool);
+
+    // Get all the property configs.
+    std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+    getAllPropertyConfigs() const override;
+
+    // Set property values asynchronously. Server could return before the property set requests
+    // are sent to vehicle bus or before property set confirmation is received. The callback is
+    // safe to be called after the function returns and is safe to be called in a different thread.
+    ::aidl::android::hardware::automotive::vehicle::StatusCode setValues(
+            std::shared_ptr<const SetValuesCallback> callback,
+            const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest>&
+                    requests) override;
+
+    // Get property values asynchronously. Server could return before the property values are ready.
+    // The callback is safe to be called after the function returns and is safe to be called in a
+    // different thread.
+    ::aidl::android::hardware::automotive::vehicle::StatusCode getValues(
+            std::shared_ptr<const GetValuesCallback> callback,
+            const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest>&
+                    requests) const override;
+
+    // Dump debug information in the server.
+    DumpResult dump(const std::vector<std::string>& options) override;
+
+    // Check whether the system is healthy, return {@code StatusCode::OK} for healthy.
+    ::aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() override;
+
+    // Register a callback that would be called when there is a property change event from vehicle.
+    void registerOnPropertyChangeEvent(
+            std::unique_ptr<const PropertyChangeCallback> callback) override;
+
+    // Register a callback that would be called when there is a property set error event from
+    // vehicle.
+    void registerOnPropertySetErrorEvent(
+            std::unique_ptr<const PropertySetErrorCallback> callback) override;
+
+  private:
+    // Expose private methods to unit test.
+    friend class FakeVehicleHardwareTestHelper;
+
+    // mValuePool is also used in mServerSidePropStore.
+    const std::shared_ptr<VehiclePropValuePool> mValuePool;
+    const std::shared_ptr<VehiclePropertyStore> mServerSidePropStore;
+    const std::unique_ptr<obd2frame::FakeObd2Frame> mFakeObd2Frame;
+    const std::unique_ptr<FakeUserHal> mFakeUserHal;
+    std::mutex mCallbackLock;
+    std::unique_ptr<const PropertyChangeCallback> mOnPropertyChangeCallback
+            GUARDED_BY(mCallbackLock);
+    std::unique_ptr<const PropertySetErrorCallback> mOnPropertySetErrorCallback
+            GUARDED_BY(mCallbackLock);
+
+    void init();
+    // Stores the initial value to property store.
+    void storePropInitialValue(const defaultconfig::ConfigDeclaration& config);
+    // The callback that would be called when a vehicle property value change happens.
+    void onValueChangeCallback(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+    // If property "persist.vendor.vhal_init_value_override" is set to true, override the properties
+    // using config files in 'overrideDir'.
+    void maybeOverrideProperties(const char* overrideDir);
+    // Override the properties using config files in 'overrideDir'.
+    void overrideProperties(const char* overrideDir);
+
+    ::android::base::Result<void> maybeSetSpecialValue(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
+            bool* isSpecialValue);
+    ::android::base::Result<VehiclePropValuePool::RecyclableType> maybeGetSpecialValue(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
+            bool* isSpecialValue) const;
+    ::android::base::Result<void> setApPowerStateReport(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+    VehiclePropValuePool::RecyclableType createApPowerStateReq(
+            ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq state);
+    ::android::base::Result<void> setUserHalProp(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+    ::android::base::Result<VehiclePropValuePool::RecyclableType> getUserHalProp(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
+    bool isHvacPropAndHvacNotAvailable(int32_t propId);
+};
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
new file mode 100644
index 0000000..e75f0e7
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -0,0 +1,551 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "FakeVehicleHardware.h"
+
+#include <DefaultConfig.h>
+#include <FakeObd2Frame.h>
+#include <JsonFakeValueGenerator.h>
+#include <PropertyUtils.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+#include <android-base/properties.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+#include <dirent.h>
+#include <sys/types.h>
+#include <fstream>
+#include <regex>
+#include <unordered_set>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
+using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
+using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+using ::android::base::Error;
+using ::android::base::Result;
+
+const char* VENDOR_OVERRIDE_DIR = "/vendor/etc/automotive/vhaloverride/";
+const char* OVERRIDE_PROPERTY = "persist.vendor.vhal_init_value_override";
+
+}  // namespace
+
+void FakeVehicleHardware::storePropInitialValue(const defaultconfig::ConfigDeclaration& config) {
+    const VehiclePropConfig& vehiclePropConfig = config.config;
+    int propId = vehiclePropConfig.prop;
+
+    // A global property will have only a single area
+    bool globalProp = isGlobalProp(propId);
+    size_t numAreas = globalProp ? 1 : vehiclePropConfig.areaConfigs.size();
+
+    for (size_t i = 0; i < numAreas; i++) {
+        int32_t curArea = globalProp ? 0 : vehiclePropConfig.areaConfigs[i].areaId;
+
+        // Create a separate instance for each individual zone
+        VehiclePropValue prop = {
+                .areaId = curArea,
+                .prop = propId,
+                .timestamp = elapsedRealtimeNano(),
+        };
+
+        if (config.initialAreaValues.empty()) {
+            if (config.initialValue == RawPropValues{}) {
+                // Skip empty initial values.
+                continue;
+            }
+            prop.value = config.initialValue;
+        } else if (auto valueForAreaIt = config.initialAreaValues.find(curArea);
+                   valueForAreaIt != config.initialAreaValues.end()) {
+            prop.value = valueForAreaIt->second;
+        } else {
+            ALOGW("failed to get default value for prop 0x%x area 0x%x", propId, curArea);
+            continue;
+        }
+
+        auto result =
+                mServerSidePropStore->writeValue(mValuePool->obtain(prop), /*updateStatus=*/true);
+        if (!result.ok()) {
+            ALOGE("failed to write default config value, error: %s, status: %d",
+                  getErrorMsg(result).c_str(), getIntErrorCode(result));
+        }
+    }
+}
+
+FakeVehicleHardware::FakeVehicleHardware()
+    : mValuePool(new VehiclePropValuePool),
+      mServerSidePropStore(new VehiclePropertyStore(mValuePool)),
+      mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)),
+      mFakeUserHal(new FakeUserHal(mValuePool)) {
+    init();
+}
+
+FakeVehicleHardware::FakeVehicleHardware(std::unique_ptr<VehiclePropValuePool> valuePool)
+    : mValuePool(std::move(valuePool)),
+      mServerSidePropStore(new VehiclePropertyStore(mValuePool)),
+      mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)),
+      mFakeUserHal(new FakeUserHal(mValuePool)) {
+    init();
+}
+
+void FakeVehicleHardware::init() {
+    for (auto& it : defaultconfig::getDefaultConfigs()) {
+        VehiclePropConfig cfg = it.config;
+        VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
+
+        if (cfg.prop == OBD2_FREEZE_FRAME) {
+            tokenFunction = [](const VehiclePropValue& propValue) { return propValue.timestamp; };
+        }
+
+        mServerSidePropStore->registerProperty(cfg, tokenFunction);
+        if (obd2frame::FakeObd2Frame::isDiagnosticProperty(cfg)) {
+            // Ignore storing default value for diagnostic property. They have special get/set
+            // logic.
+            continue;
+        }
+        storePropInitialValue(it);
+    }
+
+    maybeOverrideProperties(VENDOR_OVERRIDE_DIR);
+
+    // OBD2_LIVE_FRAME and OBD2_FREEZE_FRAME must be configured in default configs.
+    mFakeObd2Frame->initObd2LiveFrame(*mServerSidePropStore->getConfig(OBD2_LIVE_FRAME).value());
+    mFakeObd2Frame->initObd2FreezeFrame(
+            *mServerSidePropStore->getConfig(OBD2_FREEZE_FRAME).value());
+
+    mServerSidePropStore->setOnValueChangeCallback(
+            [this](const VehiclePropValue& value) { return onValueChangeCallback(value); });
+}
+
+std::vector<VehiclePropConfig> FakeVehicleHardware::getAllPropertyConfigs() const {
+    return mServerSidePropStore->getAllConfigs();
+}
+
+VehiclePropValuePool::RecyclableType FakeVehicleHardware::createApPowerStateReq(
+        VehicleApPowerStateReq state) {
+    auto req = mValuePool->obtain(VehiclePropertyType::INT32_VEC, 2);
+    req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
+    req->areaId = 0;
+    req->timestamp = elapsedRealtimeNano();
+    req->status = VehiclePropertyStatus::AVAILABLE;
+    req->value.int32Values[0] = toInt(state);
+    // Param = 0.
+    req->value.int32Values[1] = 0;
+    return req;
+}
+
+Result<void> FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) {
+    auto updatedValue = mValuePool->obtain(value);
+    updatedValue->timestamp = elapsedRealtimeNano();
+
+    if (auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
+        !writeResult.ok()) {
+        return Error(getIntErrorCode(writeResult))
+               << "failed to write value into property store, error: " << getErrorMsg(writeResult);
+    }
+
+    VehiclePropValuePool::RecyclableType prop;
+    int32_t state = value.value.int32Values[0];
+    switch (state) {
+        case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
+            [[fallthrough]];
+        case toInt(VehicleApPowerStateReport::HIBERNATION_EXIT):
+            [[fallthrough]];
+        case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
+            [[fallthrough]];
+        case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
+            // CPMS is in WAIT_FOR_VHAL state, simply move to ON
+            // Send back to HAL
+            // ALWAYS update status for generated property value
+            prop = createApPowerStateReq(VehicleApPowerStateReq::ON);
+            if (auto writeResult =
+                        mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true);
+                !writeResult.ok()) {
+                return Error(getIntErrorCode(writeResult))
+                       << "failed to write AP_POWER_STATE_REQ into property store, error: "
+                       << getErrorMsg(writeResult);
+            }
+            break;
+        case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
+            [[fallthrough]];
+        case toInt(VehicleApPowerStateReport::HIBERNATION_ENTRY):
+            [[fallthrough]];
+        case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
+            // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
+            // Send back to HAL
+            // ALWAYS update status for generated property value
+            prop = createApPowerStateReq(VehicleApPowerStateReq::FINISHED);
+            if (auto writeResult =
+                        mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true);
+                !writeResult.ok()) {
+                return Error(getIntErrorCode(writeResult))
+                       << "failed to write AP_POWER_STATE_REQ into property store, error: "
+                       << getErrorMsg(writeResult);
+            }
+            break;
+        default:
+            ALOGE("Unknown VehicleApPowerStateReport: %d", state);
+            break;
+    }
+    return {};
+}
+
+bool FakeVehicleHardware::isHvacPropAndHvacNotAvailable(int32_t propId) {
+    std::unordered_set<int32_t> powerProps(std::begin(HVAC_POWER_PROPERTIES),
+                                           std::end(HVAC_POWER_PROPERTIES));
+    if (powerProps.count(propId)) {
+        auto hvacPowerOnResult =
+                mServerSidePropStore->readValue(toInt(VehicleProperty::HVAC_POWER_ON), HVAC_ALL);
+
+        if (hvacPowerOnResult.ok() && hvacPowerOnResult.value()->value.int32Values.size() == 1 &&
+            hvacPowerOnResult.value()->value.int32Values[0] == 0) {
+            return true;
+        }
+    }
+    return false;
+}
+
+Result<void> FakeVehicleHardware::setUserHalProp(const VehiclePropValue& value) {
+    auto result = mFakeUserHal->onSetProperty(value);
+    if (!result.ok()) {
+        return Error(getIntErrorCode(result))
+               << "onSetProperty(): HAL returned error: " << getErrorMsg(result);
+    }
+    auto& updatedValue = result.value();
+    if (updatedValue != nullptr) {
+        ALOGI("onSetProperty(): updating property returned by HAL: %s",
+              updatedValue->toString().c_str());
+        if (auto writeResult = mServerSidePropStore->writeValue(std::move(result.value()));
+            !writeResult.ok()) {
+            return Error(getIntErrorCode(writeResult))
+                   << "failed to write value into property store, error: "
+                   << getErrorMsg(writeResult);
+        }
+    }
+    return {};
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeVehicleHardware::getUserHalProp(
+        const VehiclePropValue& value) const {
+    auto propId = value.prop;
+    ALOGI("get(): getting value for prop %d from User HAL", propId);
+
+    auto result = mFakeUserHal->onGetProperty(value);
+    if (!result.ok()) {
+        return Error(getIntErrorCode(result))
+               << "get(): User HAL returned error: " << getErrorMsg(result);
+    } else {
+        auto& gotValue = result.value();
+        if (gotValue != nullptr) {
+            ALOGI("get(): User HAL returned value: %s", gotValue->toString().c_str());
+            gotValue->timestamp = elapsedRealtimeNano();
+            return result;
+        } else {
+            return Error(toInt(StatusCode::INTERNAL_ERROR))
+                   << "get(): User HAL returned null value";
+        }
+    }
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeVehicleHardware::maybeGetSpecialValue(
+        const VehiclePropValue& value, bool* isSpecialValue) const {
+    *isSpecialValue = false;
+    int32_t propId = value.prop;
+    Result<VehiclePropValuePool::RecyclableType> result;
+
+    if (mFakeUserHal->isSupported(propId)) {
+        *isSpecialValue = true;
+        return getUserHalProp(value);
+    }
+
+    switch (propId) {
+        case OBD2_FREEZE_FRAME:
+            *isSpecialValue = true;
+            result = mFakeObd2Frame->getObd2FreezeFrame(value);
+            if (result.ok()) {
+                result.value()->timestamp = elapsedRealtimeNano();
+            }
+            return result;
+        case OBD2_FREEZE_FRAME_INFO:
+            *isSpecialValue = true;
+            result = mFakeObd2Frame->getObd2DtcInfo();
+            if (result.ok()) {
+                result.value()->timestamp = elapsedRealtimeNano();
+            }
+            return result;
+        default:
+            // Do nothing.
+            break;
+    }
+
+    return nullptr;
+}
+
+Result<void> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value,
+                                                       bool* isSpecialValue) {
+    *isSpecialValue = false;
+    VehiclePropValuePool::RecyclableType updatedValue;
+    int32_t propId = value.prop;
+
+    if (mFakeUserHal->isSupported(propId)) {
+        *isSpecialValue = true;
+        return setUserHalProp(value);
+    }
+
+    if (isHvacPropAndHvacNotAvailable(propId)) {
+        *isSpecialValue = true;
+        return Error(toInt(StatusCode::NOT_AVAILABLE)) << "hvac not available";
+    }
+
+    switch (propId) {
+        case toInt(VehicleProperty::AP_POWER_STATE_REPORT):
+            *isSpecialValue = true;
+            return setApPowerStateReport(value);
+        case toInt(VehicleProperty::VEHICLE_MAP_SERVICE):
+            // Placeholder for future implementation of VMS property in the default hal. For
+            // now, just returns OK; otherwise, hal clients crash with property not supported.
+            *isSpecialValue = true;
+            return {};
+        case OBD2_FREEZE_FRAME_CLEAR:
+            *isSpecialValue = true;
+            return mFakeObd2Frame->clearObd2FreezeFrames(value);
+
+#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+        case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
+            [[fallthrough]];
+        case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
+            [[fallthrough]];
+        case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE):
+            [[fallthrough]];
+        case VENDOR_CLUSTER_SWITCH_UI:
+            [[fallthrough]];
+        case VENDOR_CLUSTER_DISPLAY_STATE:
+            *isSpecialValue = true;
+            updatedValue = mValuePool->obtain(getPropType(value.prop));
+            updatedValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK);
+            if (getPropGroup(value.prop) == VehiclePropertyGroup::SYSTEM) {
+                updatedValue->prop |= toInt(VehiclePropertyGroup::VENDOR);
+            } else {
+                updatedValue->prop |= toInt(VehiclePropertyGroup::SYSTEM);
+            }
+            updatedValue->value = value.value;
+            updatedValue->timestamp = elapsedRealtimeNano();
+            updatedValue->areaId = value.areaId;
+            if (auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
+                !writeResult.ok()) {
+                return Error(getIntErrorCode(writeResult))
+                       << "failed to write value into property store, error: "
+                       << getErrorMsg(writeResult);
+            }
+            return {};
+#endif  // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+
+        default:
+            break;
+    }
+    return {};
+}
+
+StatusCode FakeVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback,
+                                          const std::vector<SetValueRequest>& requests) {
+    std::vector<VehiclePropValue> updatedValues;
+    std::vector<SetValueResult> results;
+    for (auto& request : requests) {
+        const VehiclePropValue& value = request.value;
+        int propId = value.prop;
+
+        ALOGD("Set value for property ID: %d", propId);
+
+        SetValueResult setValueResult;
+        setValueResult.requestId = request.requestId;
+        setValueResult.status = StatusCode::OK;
+
+        bool isSpecialValue = false;
+        auto setSpecialValueResult = maybeSetSpecialValue(value, &isSpecialValue);
+
+        if (isSpecialValue) {
+            if (!setSpecialValueResult.ok()) {
+                ALOGE("failed to set special value for property ID: %d, error: %s, status: %d",
+                      propId, getErrorMsg(setSpecialValueResult).c_str(),
+                      getIntErrorCode(setSpecialValueResult));
+                setValueResult.status = getErrorCode(setSpecialValueResult);
+            }
+
+            // Special values are already handled.
+            results.push_back(std::move(setValueResult));
+            continue;
+        }
+
+        auto updatedValue = mValuePool->obtain(value);
+        int64_t timestamp = elapsedRealtimeNano();
+        updatedValue->timestamp = timestamp;
+
+        auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
+        if (!writeResult.ok()) {
+            ALOGE("failed to write value into property store, error: %s, code: %d",
+                  getErrorMsg(writeResult).c_str(), getIntErrorCode(writeResult));
+            setValueResult.status = getErrorCode(writeResult);
+        }
+        results.push_back(std::move(setValueResult));
+    }
+
+    // In the real vhal, the values will be sent to Car ECU. We just pretend it is done here and
+    // send back the updated property values to client.
+    (*callback)(std::move(results));
+
+    return StatusCode::OK;
+}
+
+StatusCode FakeVehicleHardware::getValues(std::shared_ptr<const GetValuesCallback> callback,
+                                          const std::vector<GetValueRequest>& requests) const {
+    std::vector<GetValueResult> results;
+    for (auto& request : requests) {
+        const VehiclePropValue& value = request.prop;
+        ALOGD("getValues(%d)", value.prop);
+
+        GetValueResult getValueResult;
+        getValueResult.requestId = request.requestId;
+        bool isSpecialValue = false;
+
+        auto result = maybeGetSpecialValue(value, &isSpecialValue);
+        if (isSpecialValue) {
+            if (!result.ok()) {
+                ALOGE("failed to get special value: %d, error: %s, code: %d", value.prop,
+                      getErrorMsg(result).c_str(), getIntErrorCode(result));
+                getValueResult.status = getErrorCode(result);
+            } else {
+                getValueResult.status = StatusCode::OK;
+                getValueResult.prop = *result.value();
+            }
+            results.push_back(std::move(getValueResult));
+            continue;
+        }
+
+        auto readResult = mServerSidePropStore->readValue(value);
+        if (!readResult.ok()) {
+            StatusCode errorCode = getErrorCode(readResult);
+            if (errorCode == StatusCode::NOT_AVAILABLE) {
+                ALOGW("%s", "value has not been set yet");
+            } else {
+                ALOGE("failed to get value, error: %s, code: %d", getErrorMsg(readResult).c_str(),
+                      toInt(errorCode));
+            }
+            getValueResult.status = errorCode;
+        } else {
+            getValueResult.status = StatusCode::OK;
+            getValueResult.prop = *readResult.value();
+        }
+        results.push_back(std::move(getValueResult));
+    }
+
+    (*callback)(std::move(results));
+
+    return StatusCode::OK;
+}
+
+DumpResult FakeVehicleHardware::dump(const std::vector<std::string>&) {
+    DumpResult result;
+    // TODO(b/201830716): Implement this.
+    return result;
+}
+
+StatusCode FakeVehicleHardware::checkHealth() {
+    // TODO(b/201830716): Implement this.
+    return StatusCode::OK;
+}
+
+void FakeVehicleHardware::registerOnPropertyChangeEvent(
+        std::unique_ptr<const PropertyChangeCallback> callback) {
+    std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
+    mOnPropertyChangeCallback = std::move(callback);
+}
+
+void FakeVehicleHardware::registerOnPropertySetErrorEvent(
+        std::unique_ptr<const PropertySetErrorCallback> callback) {
+    std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
+    mOnPropertySetErrorCallback = std::move(callback);
+}
+
+void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) {
+    std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
+
+    if (mOnPropertyChangeCallback == nullptr) {
+        return;
+    }
+
+    std::vector<VehiclePropValue> updatedValues;
+    updatedValues.push_back(value);
+    (*mOnPropertyChangeCallback)(std::move(updatedValues));
+}
+
+void FakeVehicleHardware::maybeOverrideProperties(const char* overrideDir) {
+    if (android::base::GetBoolProperty(OVERRIDE_PROPERTY, false)) {
+        overrideProperties(overrideDir);
+    }
+}
+
+void FakeVehicleHardware::overrideProperties(const char* overrideDir) {
+    ALOGI("loading vendor override properties from %s", overrideDir);
+    if (auto dir = opendir(overrideDir); dir != NULL) {
+        std::regex regJson(".*[.]json", std::regex::icase);
+        while (auto f = readdir(dir)) {
+            if (!std::regex_match(f->d_name, regJson)) {
+                continue;
+            }
+            std::string file = overrideDir + std::string(f->d_name);
+            JsonFakeValueGenerator tmpGenerator(file);
+
+            std::vector<VehiclePropValue> propValues = tmpGenerator.getAllEvents();
+            for (const VehiclePropValue& prop : propValues) {
+                auto propToStore = mValuePool->obtain(prop);
+                propToStore->timestamp = elapsedRealtimeNano();
+                if (auto result = mServerSidePropStore->writeValue(std::move(propToStore),
+                                                                   /*updateStatus=*/true);
+                    !result.ok()) {
+                    ALOGW("failed to write vendor override properties: %d, error: %s, code: %d",
+                          prop.prop, getErrorMsg(result).c_str(), getIntErrorCode(result));
+                }
+            }
+        }
+        closedir(dir);
+    }
+}
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
new file mode 100644
index 0000000..90d1516
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "FakeVehicleHardwareTest",
+    vendor: true,
+    srcs: ["*.cpp"],
+    cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
+    header_libs: [
+        "IVehicleHardware",
+        "VehicleHalDefaultConfig",
+        "VehicleHalTestUtilHeaders",
+    ],
+    static_libs: [
+        "VehicleHalUtils",
+        "FakeVehicleHardware",
+        "FakeVehicleHalValueGenerators",
+        "FakeObd2Frame",
+        "FakeUserHal",
+        "libgtest",
+        "libgmock",
+    ],
+    shared_libs: [
+        "libjsoncpp",
+    ],
+    data: [
+        ":FakeVehicleHardwareTestOverrideJson",
+    ],
+    defaults: ["VehicleHalDefaults"],
+    test_suites: ["device-tests"],
+}
+
+filegroup {
+    name: "FakeVehicleHardwareTestOverrideJson",
+    srcs: ["override/*"],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
new file mode 100644
index 0000000..f8df6e6
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -0,0 +1,1210 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <FakeVehicleHardware.h>
+
+#include <DefaultConfig.h>
+#include <FakeObd2Frame.h>
+#include <FakeUserHal.h>
+#include <PropertyUtils.h>
+#include <TestPropertyUtils.h>
+
+#include <android-base/expected.h>
+#include <android-base/file.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+#include <inttypes.h>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
+using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
+using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::android::base::expected;
+using ::android::base::unexpected;
+using ::testing::ContainerEq;
+using ::testing::Eq;
+using ::testing::IsSubsetOf;
+using ::testing::WhenSortedBy;
+
+constexpr int INVALID_PROP_ID = 0;
+
+}  // namespace
+
+// A helper class to access private methods for FakeVehicleHardware.
+class FakeVehicleHardwareTestHelper {
+  public:
+    FakeVehicleHardwareTestHelper(FakeVehicleHardware* hardware) { mHardware = hardware; }
+
+    void overrideProperties(const char* overrideDir) { mHardware->overrideProperties(overrideDir); }
+
+  private:
+    FakeVehicleHardware* mHardware;
+};
+
+class FakeVehicleHardwareTest : public ::testing::Test {
+  protected:
+    void SetUp() override {
+        auto callback = std::make_unique<IVehicleHardware::PropertyChangeCallback>(
+                [this](const std::vector<VehiclePropValue>& values) {
+                    onPropertyChangeEvent(values);
+                });
+        getHardware()->registerOnPropertyChangeEvent(std::move(callback));
+        mSetValuesCallback = std::make_shared<IVehicleHardware::SetValuesCallback>(
+                [this](std::vector<SetValueResult> results) { onSetValues(results); });
+        mGetValuesCallback = std::make_shared<IVehicleHardware::GetValuesCallback>(
+                [this](std::vector<GetValueResult> results) { onGetValues(results); });
+    }
+
+    FakeVehicleHardware* getHardware() { return &mHardware; }
+
+    StatusCode setValues(const std::vector<SetValueRequest>& requests) {
+        return getHardware()->setValues(mSetValuesCallback, requests);
+    }
+
+    StatusCode getValues(const std::vector<GetValueRequest>& requests) {
+        return getHardware()->getValues(mGetValuesCallback, requests);
+    }
+
+    StatusCode setValue(const VehiclePropValue& value) {
+        std::vector<SetValueRequest> requests = {
+                SetValueRequest{
+                        .requestId = 0,
+                        .value = value,
+                },
+        };
+
+        if (StatusCode status = setValues(requests); status != StatusCode::OK) {
+            return status;
+        }
+
+        const SetValueResult& result = getSetValueResults().back();
+
+        if (result.requestId != 0) {
+            ALOGE("request ID mismatch, got %" PRId64 ", expect 0", result.requestId);
+            return StatusCode::INTERNAL_ERROR;
+        }
+
+        return result.status;
+    }
+
+    expected<VehiclePropValue, StatusCode> getValue(const VehiclePropValue& value) {
+        std::vector<GetValueRequest> requests = {
+                GetValueRequest{
+                        .requestId = 0,
+                        .prop = value,
+                },
+        };
+
+        if (StatusCode status = getValues(requests); status != StatusCode::OK) {
+            return unexpected(status);
+        }
+
+        const GetValueResult& result = getGetValueResults().back();
+        if (result.requestId != 0) {
+            ALOGE("request ID mismatch, got %" PRId64 ", expect 0", result.requestId);
+            return unexpected(StatusCode::INTERNAL_ERROR);
+        }
+
+        if (result.status != StatusCode::OK) {
+            return unexpected(result.status);
+        }
+
+        if (!result.prop.has_value()) {
+            ALOGE("%s", "result property is empty");
+            return unexpected(StatusCode::INTERNAL_ERROR);
+        }
+
+        return result.prop.value();
+    }
+
+    template <class T>
+    int getStatus(expected<T, StatusCode> result) {
+        return toInt(result.error());
+    }
+
+    void onSetValues(const std::vector<SetValueResult> results) {
+        for (auto& result : results) {
+            mSetValueResults.push_back(result);
+        }
+    }
+
+    const std::vector<SetValueResult>& getSetValueResults() { return mSetValueResults; }
+
+    void onGetValues(const std::vector<GetValueResult> results) {
+        for (auto& result : results) {
+            mGetValueResults.push_back(result);
+        }
+    }
+
+    const std::vector<GetValueResult>& getGetValueResults() { return mGetValueResults; }
+
+    void onPropertyChangeEvent(const std::vector<VehiclePropValue>& values) {
+        for (auto& value : values) {
+            mChangedProperties.push_back(value);
+        }
+    }
+
+    const std::vector<VehiclePropValue>& getChangedProperties() { return mChangedProperties; }
+
+    void clearChangedProperties() { mChangedProperties.clear(); }
+
+    static void addSetValueRequest(std::vector<SetValueRequest>& requests,
+                                   std::vector<SetValueResult>& expectedResults, int64_t requestId,
+                                   const VehiclePropValue& value, StatusCode expectedStatus) {
+        SetValueRequest request;
+        request.requestId = requestId;
+        request.value = value;
+        request.value.timestamp = elapsedRealtimeNano();
+        requests.push_back(std::move(request));
+
+        SetValueResult result;
+        result.requestId = requestId;
+        result.status = expectedStatus;
+        expectedResults.push_back(std::move(result));
+    }
+
+    static void addGetValueRequest(std::vector<GetValueRequest>& requests,
+                                   std::vector<GetValueResult>& expectedResults, int64_t requestId,
+                                   const VehiclePropValue& value, StatusCode expectedStatus) {
+        GetValueRequest request;
+        request.requestId = requestId;
+        request.prop.prop = value.prop;
+        request.prop.areaId = value.areaId;
+        requests.push_back(std::move(request));
+
+        GetValueResult result;
+        result.requestId = requestId;
+        result.status = expectedStatus;
+        if (expectedStatus == StatusCode::OK) {
+            result.prop = value;
+        }
+        expectedResults.push_back(std::move(result));
+    }
+
+    std::vector<VehiclePropValue> getTestPropValues() {
+        VehiclePropValue fuelCapacity = {
+                .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+                .value = {.floatValues = {1.0}},
+        };
+
+        VehiclePropValue leftTirePressure = {
+                .prop = toInt(VehicleProperty::TIRE_PRESSURE),
+                .value = {.floatValues = {170.0}},
+                .areaId = WHEEL_FRONT_LEFT,
+        };
+
+        VehiclePropValue rightTirePressure = {
+                .prop = toInt(VehicleProperty::TIRE_PRESSURE),
+                .value = {.floatValues = {180.0}},
+                .areaId = WHEEL_FRONT_RIGHT,
+        };
+
+        return {fuelCapacity, leftTirePressure, rightTirePressure};
+    }
+
+    struct PropValueCmp {
+        bool operator()(const VehiclePropValue& a, const VehiclePropValue& b) const {
+            return (a.prop < b.prop) || ((a.prop == b.prop) && (a.value < b.value)) ||
+                   ((a.prop == b.prop) && (a.value == b.value) && (a.areaId < b.areaId));
+        }
+    } mPropValueCmp;
+
+  private:
+    FakeVehicleHardware mHardware;
+    std::vector<SetValueResult> mSetValueResults;
+    std::vector<GetValueResult> mGetValueResults;
+    std::vector<VehiclePropValue> mChangedProperties;
+    std::shared_ptr<IVehicleHardware::SetValuesCallback> mSetValuesCallback;
+    std::shared_ptr<IVehicleHardware::GetValuesCallback> mGetValuesCallback;
+};
+
+TEST_F(FakeVehicleHardwareTest, testGetAllPropertyConfigs) {
+    std::vector<VehiclePropConfig> configs = getHardware()->getAllPropertyConfigs();
+
+    ASSERT_EQ(configs.size(), defaultconfig::getDefaultConfigs().size());
+}
+
+TEST_F(FakeVehicleHardwareTest, testGetDefaultValues) {
+    std::vector<GetValueRequest> getValueRequests;
+    std::vector<GetValueResult> expectedGetValueResults;
+    int64_t requestId = 1;
+
+    for (auto& config : defaultconfig::getDefaultConfigs()) {
+        if (obd2frame::FakeObd2Frame::isDiagnosticProperty(config.config)) {
+            // Ignore storing default value for diagnostic property. They have special get/set
+            // logic.
+            continue;
+        }
+
+        if (FakeUserHal::isSupported(config.config.prop)) {
+            // Ignore fake user HAL properties, they have special logic for getting values.
+            continue;
+        }
+
+        int propId = config.config.prop;
+        if (isGlobalProp(propId)) {
+            if (config.initialValue == RawPropValues{}) {
+                addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++,
+                                   VehiclePropValue{.prop = propId}, StatusCode::NOT_AVAILABLE);
+                continue;
+            }
+            addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++,
+                               VehiclePropValue{
+                                       .prop = propId,
+                                       .value = config.initialValue,
+                               },
+                               StatusCode::OK);
+            continue;
+        }
+        for (auto areaConfig : config.config.areaConfigs) {
+            StatusCode status = StatusCode::OK;
+            VehiclePropValue propValue{
+                    .prop = propId,
+                    .areaId = areaConfig.areaId,
+            };
+            if (config.initialAreaValues.empty()) {
+                if (config.initialValue == RawPropValues{}) {
+                    status = StatusCode::NOT_AVAILABLE;
+                } else {
+                    propValue.value = config.initialValue;
+                }
+            } else if (auto valueForAreaIt = config.initialAreaValues.find(areaConfig.areaId);
+                       valueForAreaIt != config.initialAreaValues.end()) {
+                propValue.value = valueForAreaIt->second;
+            } else {
+                status = StatusCode::NOT_AVAILABLE;
+            }
+            addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, propValue,
+                               status);
+        }
+    }
+
+    // In our implementation, this would finish immediately.
+    StatusCode status = getValues(getValueRequests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    std::vector<GetValueResult> getValueResultsWithNoTimestamp;
+    for (auto& result : getGetValueResults()) {
+        GetValueResult resultCopy = result;
+        resultCopy.prop->timestamp = 0;
+        getValueResultsWithNoTimestamp.push_back(std::move(resultCopy));
+    }
+    ASSERT_THAT(getValueResultsWithNoTimestamp, ContainerEq(expectedGetValueResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetValues) {
+    std::vector<SetValueRequest> requests;
+    std::vector<SetValueResult> expectedResults;
+
+    int64_t requestId = 1;
+    for (auto& value : getTestPropValues()) {
+        addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK);
+    }
+
+    StatusCode status = setValues(requests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    // Although callback might be called asynchronously, in our implementation, the callback would
+    // be called before setValues returns.
+    ASSERT_THAT(getSetValueResults(), ContainerEq(expectedResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetValuesError) {
+    std::vector<SetValueRequest> requests;
+    std::vector<SetValueResult> expectedResults;
+
+    int64_t requestId = 1;
+
+    VehiclePropValue invalidProp = {
+            .prop = INVALID_PROP_ID,
+    };
+    addSetValueRequest(requests, expectedResults, requestId++, invalidProp,
+                       StatusCode::INVALID_ARG);
+
+    for (auto& value : getTestPropValues()) {
+        addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK);
+    }
+
+    StatusCode status = setValues(requests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    // Although callback might be called asynchronously, in our implementation, the callback would
+    // be called before setValues returns.
+    ASSERT_THAT(getSetValueResults(), ContainerEq(expectedResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testRegisterOnPropertyChangeEvent) {
+    // We have already registered this callback in Setup, here we are registering again.
+    auto callback = std::make_unique<IVehicleHardware::PropertyChangeCallback>(
+            [this](const std::vector<VehiclePropValue>& values) { onPropertyChangeEvent(values); });
+    getHardware()->registerOnPropertyChangeEvent(std::move(callback));
+
+    auto testValues = getTestPropValues();
+    std::vector<SetValueRequest> requests;
+    std::vector<SetValueResult> expectedResults;
+    int64_t requestId = 1;
+    for (auto& value : testValues) {
+        addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK);
+    }
+    int64_t timestamp = elapsedRealtimeNano();
+
+    StatusCode status = setValues(requests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    auto updatedValues = getChangedProperties();
+    std::vector<VehiclePropValue> updatedValuesWithNoTimestamp;
+    for (auto& value : updatedValues) {
+        ASSERT_GE(value.timestamp, timestamp);
+        VehiclePropValue valueCopy = value;
+        valueCopy.timestamp = 0;
+        updatedValuesWithNoTimestamp.push_back(std::move(valueCopy));
+    }
+
+    ASSERT_THAT(updatedValuesWithNoTimestamp, WhenSortedBy(mPropValueCmp, Eq(testValues)));
+}
+
+TEST_F(FakeVehicleHardwareTest, testReadValues) {
+    std::vector<SetValueRequest> setValueRequests;
+    std::vector<SetValueResult> expectedSetValueResults;
+
+    int64_t requestId = 1;
+    for (auto& value : getTestPropValues()) {
+        addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, value,
+                           StatusCode::OK);
+    }
+    int64_t timestamp = elapsedRealtimeNano();
+
+    // In our implementation, this would finish immediately.
+    StatusCode status = setValues(setValueRequests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    std::vector<GetValueRequest> getValueRequests;
+    std::vector<GetValueResult> expectedGetValueResults;
+    for (auto& value : getTestPropValues()) {
+        addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, value,
+                           StatusCode::OK);
+    }
+
+    // In our implementation, this would finish immediately.
+    status = getValues(getValueRequests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    std::vector<GetValueResult> getValueResultsWithNoTimestamp;
+    for (auto& result : getGetValueResults()) {
+        ASSERT_GE(result.prop->timestamp, timestamp);
+        GetValueResult resultCopy = result;
+        resultCopy.prop->timestamp = 0;
+        getValueResultsWithNoTimestamp.push_back(std::move(resultCopy));
+    }
+    ASSERT_THAT(getValueResultsWithNoTimestamp, ContainerEq(expectedGetValueResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testReadValuesErrorInvalidProp) {
+    std::vector<SetValueRequest> setValueRequests;
+    std::vector<SetValueResult> expectedSetValueResults;
+
+    int64_t requestId = 1;
+    for (auto& value : getTestPropValues()) {
+        addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, value,
+                           StatusCode::OK);
+    }
+
+    // In our implementation, this would finish immediately.
+    StatusCode status = setValues(setValueRequests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    std::vector<GetValueRequest> getValueRequests;
+    std::vector<GetValueResult> expectedGetValueResults;
+    VehiclePropValue invalidProp = {
+            .prop = INVALID_PROP_ID,
+    };
+    addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, invalidProp,
+                       StatusCode::INVALID_ARG);
+
+    // In our implementation, this would finish immediately.
+    status = getValues(getValueRequests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+    ASSERT_THAT(getGetValueResults(), ContainerEq(expectedGetValueResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testReadValuesErrorNotAvailable) {
+    std::vector<GetValueRequest> getValueRequests;
+    std::vector<GetValueResult> expectedGetValueResults;
+    // VEHICLE_MAP_SERVICE does not have initial value, 'get' must always return
+    // StatusCode::NOT_AVAILABLE.
+    addGetValueRequest(getValueRequests, expectedGetValueResults, 0,
+                       VehiclePropValue{
+                               .prop = VEHICLE_MAP_SERVICE,
+                       },
+                       StatusCode::NOT_AVAILABLE);
+
+    // In our implementation, this would finish immediately.
+    StatusCode status = getValues(getValueRequests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+    ASSERT_THAT(getGetValueResults(), ContainerEq(expectedGetValueResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetStatusMustIgnore) {
+    VehiclePropValue testValue = getTestPropValues()[0];
+    testValue.status = VehiclePropertyStatus::UNAVAILABLE;
+
+    std::vector<SetValueRequest> setValueRequests;
+    std::vector<SetValueResult> expectedSetValueResults;
+
+    int64_t requestId = 1;
+    addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, testValue,
+                       StatusCode::OK);
+
+    // In our implementation, this would finish immediately.
+    StatusCode status = setValues(setValueRequests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+    ASSERT_THAT(getSetValueResults(), ContainerEq(expectedSetValueResults));
+
+    std::vector<GetValueRequest> getValueRequests;
+    getValueRequests.push_back(GetValueRequest{
+            .requestId = requestId++,
+            .prop = testValue,
+    });
+
+    // In our implementation, this would finish immediately.
+    status = getValues(getValueRequests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+    ASSERT_EQ(getGetValueResults().size(), static_cast<size_t>(1));
+    ASSERT_EQ(getGetValueResults()[0].status, StatusCode::OK);
+    // The status should be by-default AVAILABLE for new status.
+    ASSERT_EQ(getGetValueResults()[0].prop->status, VehiclePropertyStatus::AVAILABLE);
+
+    // Try to set the property again. The status should not be overwritten.
+    status = setValues(setValueRequests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    status = getValues(getValueRequests);
+
+    ASSERT_EQ(status, StatusCode::OK);
+    ASSERT_EQ(getGetValueResults().size(), static_cast<size_t>(2));
+    ASSERT_EQ(getGetValueResults()[1].status, StatusCode::OK);
+    ASSERT_EQ(getGetValueResults()[1].prop->status, VehiclePropertyStatus::AVAILABLE);
+}
+
+TEST_F(FakeVehicleHardwareTest, testVendorOverrideProperties) {
+    std::string overrideDir = android::base::GetExecutableDirectory() + "/override/";
+    // Set vendor override directory.
+    FakeVehicleHardwareTestHelper helper(getHardware());
+    helper.overrideProperties(overrideDir.c_str());
+
+    // This is the same as the prop in 'gear_selection.json'.
+    int gearProp = toInt(VehicleProperty::GEAR_SELECTION);
+
+    auto result = getValue(VehiclePropValue{
+            .prop = gearProp,
+    });
+
+    ASSERT_TRUE(result.ok()) << "expect to get the overridden property ok: " << getStatus(result);
+    ASSERT_EQ(static_cast<size_t>(1), result.value().value.int32Values.size());
+    ASSERT_EQ(8, result.value().value.int32Values[0]);
+
+    // If we set the value, it should update despite the override.
+    ASSERT_EQ(setValue(VehiclePropValue{
+                      .prop = gearProp,
+                      .value =
+                              {
+                                      .int32Values = {5},
+                              },
+                      .timestamp = elapsedRealtimeNano(),
+              }),
+              StatusCode::OK)
+            << "expect to set the overridden property ok";
+
+    result = getValue(VehiclePropValue{
+            .prop = gearProp,
+    });
+
+    ASSERT_TRUE(result.ok()) << "expect to get the overridden property after setting value ok";
+    ASSERT_EQ(static_cast<size_t>(1), result.value().value.int32Values.size());
+    ASSERT_EQ(5, result.value().value.int32Values[0]);
+}
+
+TEST_F(FakeVehicleHardwareTest, testVendorOverridePropertiesMultipleAreas) {
+    std::string overrideDir = android::base::GetExecutableDirectory() + "/override/";
+    // Set vendor override directory.
+    FakeVehicleHardwareTestHelper helper(getHardware());
+    helper.overrideProperties(overrideDir.c_str());
+
+    // This is the same as the prop in 'hvac_temperature_set.json'.
+    int hvacProp = toInt(VehicleProperty::HVAC_TEMPERATURE_SET);
+
+    auto result = getValue(VehiclePropValue{
+            .prop = hvacProp,
+            .areaId = HVAC_LEFT,
+    });
+
+    ASSERT_TRUE(result.ok()) << "expect to get the overridden property ok: " << getStatus(result);
+    ASSERT_EQ(static_cast<size_t>(1), result.value().value.floatValues.size());
+    ASSERT_EQ(30.0f, result.value().value.floatValues[0]);
+
+    // HVAC_RIGHT should not be affected and return the default value.
+    result = getValue(VehiclePropValue{
+            .prop = hvacProp,
+            .areaId = HVAC_RIGHT,
+    });
+
+    ASSERT_TRUE(result.ok()) << "expect to get the default property ok: " << getStatus(result);
+    ASSERT_EQ(static_cast<size_t>(1), result.value().value.floatValues.size());
+    ASSERT_EQ(20.0f, result.value().value.floatValues[0]);
+}
+
+TEST_F(FakeVehicleHardwareTest, testVendorOverridePropertiesDirDoesNotExist) {
+    // Set vendor override directory to a non-existing dir
+    FakeVehicleHardwareTestHelper helper(getHardware());
+    helper.overrideProperties("123");
+    auto result = getValue(VehiclePropValue{
+            .prop = toInt(VehicleProperty::GEAR_SELECTION),
+    });
+
+    ASSERT_TRUE(result.ok()) << "expect to get the default property ok: " << getStatus(result);
+    ASSERT_EQ(static_cast<size_t>(1), result.value().value.int32Values.size());
+    ASSERT_EQ(4, result.value().value.int32Values[0]);
+}
+
+struct SetSpecialValueTestCase {
+    std::string name;
+    std::vector<VehiclePropValue> valuesToSet;
+    std::vector<VehiclePropValue> expectedValuesToGet;
+};
+
+std::vector<SetSpecialValueTestCase> setSpecialValueTestCases() {
+    return {
+            SetSpecialValueTestCase{
+                    .name = "set_ap_power_state_report_deep_sleep_exit",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::DEEP_SLEEP_EXIT)},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::DEEP_SLEEP_EXIT)},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+                                            .status = VehiclePropertyStatus::AVAILABLE,
+                                            .value.int32Values = {toInt(VehicleApPowerStateReq::ON),
+                                                                  0},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_ap_power_state_report_hibernation_exit",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::HIBERNATION_EXIT)},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::HIBERNATION_EXIT)},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+                                            .status = VehiclePropertyStatus::AVAILABLE,
+                                            .value.int32Values = {toInt(VehicleApPowerStateReq::ON),
+                                                                  0},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_ap_power_state_report_shutdown_cancelled",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::SHUTDOWN_CANCELLED)},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::SHUTDOWN_CANCELLED)},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+                                            .status = VehiclePropertyStatus::AVAILABLE,
+                                            .value.int32Values = {toInt(VehicleApPowerStateReq::ON),
+                                                                  0},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_ap_power_state_report_wait_for_vhal",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::WAIT_FOR_VHAL)},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::WAIT_FOR_VHAL)},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+                                            .status = VehiclePropertyStatus::AVAILABLE,
+                                            .value.int32Values = {toInt(VehicleApPowerStateReq::ON),
+                                                                  0},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_ap_power_state_report_deep_sleep_entry",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::DEEP_SLEEP_ENTRY)},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::DEEP_SLEEP_ENTRY)},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+                                            .status = VehiclePropertyStatus::AVAILABLE,
+                                            .value.int32Values =
+                                                    {toInt(VehicleApPowerStateReq::FINISHED), 0},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_ap_power_state_report_hibernation_entry",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::HIBERNATION_ENTRY)},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::HIBERNATION_ENTRY)},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+                                            .status = VehiclePropertyStatus::AVAILABLE,
+                                            .value.int32Values =
+                                                    {toInt(VehicleApPowerStateReq::FINISHED), 0},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "set_ap_power_state_report_shutdown_start",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::SHUTDOWN_START)},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                                            .value.int32Values = {toInt(
+                                                    VehicleApPowerStateReport::SHUTDOWN_START)},
+                                    },
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+                                            .status = VehiclePropertyStatus::AVAILABLE,
+                                            .value.int32Values =
+                                                    {toInt(VehicleApPowerStateReq::FINISHED), 0},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "cluster_report_state_to_vendor",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CLUSTER_REPORT_STATE),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = VENDOR_CLUSTER_REPORT_STATE,
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "cluster_request_display_to_vendor",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = VENDOR_CLUSTER_REQUEST_DISPLAY,
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "cluster_navigation_state_to_vendor",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::CLUSTER_NAVIGATION_STATE),
+                                            .value.byteValues = {0x1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = VENDOR_CLUSTER_NAVIGATION_STATE,
+                                            .value.byteValues = {0x1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "vendor_cluster_switch_ui_to_system",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = VENDOR_CLUSTER_SWITCH_UI,
+                                            .value.int32Values = {1},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CLUSTER_SWITCH_UI),
+                                            .value.int32Values = {1},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "vendor_cluster_display_state_to_system",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = VENDOR_CLUSTER_DISPLAY_STATE,
+                                            .value.int32Values = {1, 2},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::CLUSTER_DISPLAY_STATE),
+                                            .value.int32Values = {1, 2},
+                                    },
+                            },
+            },
+    };
+}
+
+class FakeVehicleHardwareSpecialValuesTest
+    : public FakeVehicleHardwareTest,
+      public testing::WithParamInterface<SetSpecialValueTestCase> {};
+
+TEST_P(FakeVehicleHardwareSpecialValuesTest, testSetSpecialProperties) {
+    const SetSpecialValueTestCase& tc = GetParam();
+
+    for (const auto& value : tc.valuesToSet) {
+        ASSERT_EQ(setValue(value), StatusCode::OK) << "failed to set property " << value.prop;
+    }
+
+    std::vector<VehiclePropValue> gotValues;
+
+    for (const auto& value : tc.expectedValuesToGet) {
+        auto result = getValue(VehiclePropValue{.prop = value.prop});
+
+        ASSERT_TRUE(result.ok()) << "failed to get property " << value.prop
+                                 << " status:" << getStatus(result);
+
+        gotValues.push_back(result.value());
+        VehiclePropValue valueWithNoTimestamp = result.value();
+        valueWithNoTimestamp.timestamp = 0;
+
+        ASSERT_EQ(valueWithNoTimestamp, value);
+    }
+
+    // Some of the updated properties might be the same as default config, thus not causing
+    // a property change event. So the changed properties should be a subset of all the updated
+    // properties.
+    ASSERT_THAT(getChangedProperties(), WhenSortedBy(mPropValueCmp, IsSubsetOf(gotValues)));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        SpecialValuesTests, FakeVehicleHardwareSpecialValuesTest,
+        testing::ValuesIn(setSpecialValueTestCases()),
+        [](const testing::TestParamInfo<FakeVehicleHardwareSpecialValuesTest::ParamType>& info) {
+            return info.param.name;
+        });
+
+TEST_F(FakeVehicleHardwareTest, testGetObd2FreezeFrame) {
+    int64_t timestamp = elapsedRealtimeNano();
+
+    auto result = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
+
+    ASSERT_TRUE(result.ok());
+
+    auto propValue = result.value();
+    ASSERT_GE(propValue.timestamp, timestamp);
+    ASSERT_EQ(propValue.value.int64Values.size(), static_cast<size_t>(3))
+            << "expect 3 obd2 freeze frames stored";
+
+    for (int64_t timestamp : propValue.value.int64Values) {
+        auto freezeFrameResult = getValue(VehiclePropValue{
+                .prop = OBD2_FREEZE_FRAME,
+                .value.int64Values = {timestamp},
+        });
+
+        EXPECT_TRUE(result.ok()) << "expect to get freeze frame for timestamp " << timestamp
+                                 << " ok";
+        EXPECT_GE(freezeFrameResult.value().timestamp, timestamp);
+    }
+}
+
+TEST_F(FakeVehicleHardwareTest, testClearObd2FreezeFrame) {
+    int64_t timestamp = elapsedRealtimeNano();
+
+    auto getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
+
+    ASSERT_TRUE(getValueResult.ok());
+
+    auto propValue = getValueResult.value();
+    ASSERT_GE(propValue.timestamp, timestamp);
+    ASSERT_EQ(propValue.value.int64Values.size(), static_cast<size_t>(3))
+            << "expect 3 obd2 freeze frames stored";
+
+    // No int64Values should clear all freeze frames.
+    StatusCode status = setValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_CLEAR});
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
+
+    ASSERT_TRUE(getValueResult.ok());
+    ASSERT_EQ(getValueResult.value().value.int64Values.size(), static_cast<size_t>(0))
+            << "expect 0 obd2 freeze frames after cleared";
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetVehicleMapService) {
+    StatusCode status =
+            setValue(VehiclePropValue{.prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE)});
+
+    EXPECT_EQ(status, StatusCode::OK);
+
+    auto getValueResult =
+            getValue(VehiclePropValue{.prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE)});
+
+    EXPECT_FALSE(getValueResult.ok());
+    EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE);
+}
+
+TEST_F(FakeVehicleHardwareTest, testGetUserPropertySetOnly) {
+    for (VehicleProperty prop : std::vector<VehicleProperty>({
+                 VehicleProperty::INITIAL_USER_INFO,
+                 VehicleProperty::SWITCH_USER,
+                 VehicleProperty::CREATE_USER,
+                 VehicleProperty::REMOVE_USER,
+         })) {
+        auto result = getValue(VehiclePropValue{.prop = toInt(prop)});
+
+        EXPECT_FALSE(result.ok());
+        if (!result.ok()) {
+            EXPECT_EQ(result.error(), StatusCode::INVALID_ARG);
+        }
+    }
+}
+
+TEST_F(FakeVehicleHardwareTest, testGetUserIdAssoc) {
+    int32_t userIdAssocProp = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+
+    auto result = getValue(VehiclePropValue{.prop = userIdAssocProp});
+
+    // Default returns NOT_AVAILABLE.
+    ASSERT_FALSE(result.ok());
+    ASSERT_EQ(result.error(), StatusCode::NOT_AVAILABLE);
+
+    // This is the same example as used in User HAL Emulation doc.
+    VehiclePropValue valueToSet = {
+            .prop = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION),
+            .areaId = 1,
+            .value.int32Values = {666, 1, 1, 2},
+    };
+
+    StatusCode status = setValue(valueToSet);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    result = getValue(VehiclePropValue{
+            .prop = userIdAssocProp,
+            // Request ID
+            .value.int32Values = {1},
+    });
+
+    ASSERT_TRUE(result.ok());
+
+    auto& gotValue = result.value();
+    gotValue.timestamp = 0;
+
+    // Expect to get the same request ID.
+    valueToSet.value.int32Values[0] = 1;
+
+    ASSERT_EQ(gotValue, valueToSet);
+}
+
+TEST_F(FakeVehicleHardwareTest, testSwitchUser) {
+    // This is the same example as used in User HAL Emulation doc.
+    VehiclePropValue valueToSet = {
+            .prop = toInt(VehicleProperty::SWITCH_USER),
+            .areaId = 1,
+            .value.int32Values = {666, 3, 2},
+    };
+
+    StatusCode status = setValue(valueToSet);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    // Simulate a request from Android side.
+    VehiclePropValue switchUserRequest = {
+            .prop = toInt(VehicleProperty::SWITCH_USER),
+            .areaId = 0,
+            .value.int32Values = {666, 3},
+    };
+    // Clear existing events.
+    clearChangedProperties();
+
+    status = setValue(switchUserRequest);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    // Should generate an event for user hal response.
+    auto events = getChangedProperties();
+    ASSERT_EQ(events.size(), static_cast<size_t>(1));
+
+    events[0].timestamp = 0;
+    ASSERT_EQ(events[0], valueToSet);
+
+    // Try to get switch_user again, should return default value.
+    clearChangedProperties();
+    status = setValue(switchUserRequest);
+    ASSERT_EQ(status, StatusCode::OK);
+
+    events = getChangedProperties();
+    ASSERT_EQ(events.size(), static_cast<size_t>(1));
+    events[0].timestamp = 0;
+    ASSERT_EQ(events[0], (VehiclePropValue{
+                                 .areaId = 0,
+                                 .prop = toInt(VehicleProperty::SWITCH_USER),
+                                 .value.int32Values =
+                                         {
+                                                 // Request ID
+                                                 666,
+                                                 // VEHICLE_RESPONSE
+                                                 3,
+                                                 // SUCCESS
+                                                 1,
+                                         },
+                         }));
+}
+
+TEST_F(FakeVehicleHardwareTest, testCreateUser) {
+    // This is the same example as used in User HAL Emulation doc.
+    VehiclePropValue valueToSet = {
+            .prop = toInt(VehicleProperty::CREATE_USER),
+            .areaId = 1,
+            .value.int32Values = {666, 2},
+    };
+
+    StatusCode status = setValue(valueToSet);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    // Simulate a request from Android side.
+    VehiclePropValue createUserRequest = {
+            .prop = toInt(VehicleProperty::CREATE_USER),
+            .areaId = 0,
+            .value.int32Values = {666},
+    };
+    // Clear existing events.
+    clearChangedProperties();
+
+    status = setValue(createUserRequest);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    // Should generate an event for user hal response.
+    auto events = getChangedProperties();
+    ASSERT_EQ(events.size(), static_cast<size_t>(1));
+    events[0].timestamp = 0;
+    EXPECT_EQ(events[0], valueToSet);
+
+    // Try to get create_user again, should return default value.
+    clearChangedProperties();
+    status = setValue(createUserRequest);
+    ASSERT_EQ(status, StatusCode::OK);
+
+    events = getChangedProperties();
+    ASSERT_EQ(events.size(), static_cast<size_t>(1));
+    events[0].timestamp = 0;
+    ASSERT_EQ(events[0], (VehiclePropValue{
+                                 .areaId = 0,
+                                 .prop = toInt(VehicleProperty::CREATE_USER),
+                                 .value.int32Values =
+                                         {
+                                                 // Request ID
+                                                 666,
+                                                 // SUCCESS
+                                                 1,
+                                         },
+                         }));
+}
+
+TEST_F(FakeVehicleHardwareTest, testInitialUserInfo) {
+    // This is the same example as used in User HAL Emulation doc.
+    VehiclePropValue valueToSet = {
+            .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
+            .areaId = 1,
+            .value.int32Values = {666, 1, 11},
+    };
+
+    StatusCode status = setValue(valueToSet);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    // Simulate a request from Android side.
+    VehiclePropValue initialUserInfoRequest = {
+            .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
+            .areaId = 0,
+            .value.int32Values = {3},
+    };
+    // Clear existing events.
+    clearChangedProperties();
+
+    status = setValue(initialUserInfoRequest);
+
+    ASSERT_EQ(status, StatusCode::OK);
+
+    // Should generate an event for user hal response.
+    auto events = getChangedProperties();
+    ASSERT_EQ(events.size(), static_cast<size_t>(1));
+    events[0].timestamp = 0;
+    EXPECT_EQ(events[0], (VehiclePropValue{
+                                 .areaId = 1,
+                                 .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
+                                 .value.int32Values = {3, 1, 11},
+                         }));
+
+    // Try to get create_user again, should return default value.
+    clearChangedProperties();
+    status = setValue(initialUserInfoRequest);
+    ASSERT_EQ(status, StatusCode::OK);
+
+    events = getChangedProperties();
+    ASSERT_EQ(events.size(), static_cast<size_t>(1));
+    events[0].timestamp = 0;
+    EXPECT_EQ(events[0], (VehiclePropValue{
+                                 .areaId = 0,
+                                 .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
+                                 .value.int32Values =
+                                         {
+                                                 // Request ID
+                                                 3,
+                                                 // ACTION: DEFAULT
+                                                 0,
+                                                 // User id: 0
+                                                 0,
+                                                 // Flags: 0
+                                                 0,
+                                         },
+                                 .value.stringValue = "||",
+                         }));
+}
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/gear_selection.json b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/gear_selection.json
new file mode 100644
index 0000000..59666b8
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/gear_selection.json
@@ -0,0 +1,9 @@
+[
+  {
+    "timestamp": 1000000,
+    "areaId": 0,
+    "value": 8,
+    // GEAR_SELECTION
+    "prop": 289408000
+  }
+]
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/hvac_temperature_set.json b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/hvac_temperature_set.json
new file mode 100644
index 0000000..93a97ed
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/hvac_temperature_set.json
@@ -0,0 +1,10 @@
+[
+  {
+    "timestamp": 1000000,
+    // HVAC_LEFT
+    "areaId": 49,
+    "value": 30,
+    // HVAC_TEMPERATURE_SET
+    "prop": 358614275
+  }
+]
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/Android.bp
new file mode 100644
index 0000000..c1cee84
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/Android.bp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library {
+    name: "FakeObd2Frame",
+    vendor: true,
+    srcs: ["src/*.cpp"],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    defaults: ["VehicleHalDefaults"],
+    static_libs: [
+        "VehicleHalUtils",
+    ],
+    export_static_lib_headers: ["VehicleHalUtils"],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/FakeObd2Frame.h b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/FakeObd2Frame.h
new file mode 100644
index 0000000..118bb34
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/FakeObd2Frame.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_FakeObd2Frame_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_FakeObd2Frame_H_
+
+#include <Obd2SensorStore.h>
+#include <VehicleHalTypes.h>
+#include <VehiclePropertyStore.h>
+
+#include <android-base/result.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+namespace obd2frame {
+
+class FakeObd2Frame final {
+  public:
+    explicit FakeObd2Frame(std::shared_ptr<VehiclePropertyStore> propStore)
+        : mPropStore(propStore) {}
+
+    void initObd2LiveFrame(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig& propConfig);
+    void initObd2FreezeFrame(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig& propConfig);
+    ::android::base::Result<VehiclePropValuePool::RecyclableType> getObd2FreezeFrame(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue&
+                    requestedPropValue) const;
+    ::android::base::Result<VehiclePropValuePool::RecyclableType> getObd2DtcInfo() const;
+    ::android::base::Result<void> clearObd2FreezeFrames(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+    static bool isDiagnosticProperty(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig& propConfig);
+
+  private:
+    std::shared_ptr<VehiclePropertyStore> mPropStore;
+
+    std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(size_t numVendorIntegerSensors,
+                                                          size_t numVendorFloatSensors);
+};
+
+}  // namespace obd2frame
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_FakeObd2Frame_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/Obd2SensorStore.h b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/Obd2SensorStore.h
new file mode 100644
index 0000000..f6075cb
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/Obd2SensorStore.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_Obd2SensorStore_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_Obd2SensorStore_H_
+
+#include <VehicleHalTypes.h>
+#include <VehicleObjectPool.h>
+#include <VehicleUtils.h>
+
+#include <android-base/result.h>
+
+#include <memory>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+namespace obd2frame {
+
+// This class wraps all the logic required to create an OBD2 frame.
+// It allows storing sensor values, setting appropriate bitmasks as needed, and returning
+// appropriately laid out storage of sensor values suitable for being returned via a VehicleHal
+// implementation.
+class Obd2SensorStore final {
+  public:
+    // Creates a sensor storage with a given number of vendor-specific sensors.
+    Obd2SensorStore(std::shared_ptr<VehiclePropValuePool> valuePool, size_t numVendorIntegerSensors,
+                    size_t numVendorFloatSensors);
+
+    template <class T>
+    static int getLastIndex() {
+        auto range = ::ndk::enum_range<T>();
+        auto it = range.begin();
+        while (std::next(it) != range.end()) {
+            it++;
+        }
+        return toInt(*it);
+    }
+
+    // Stores an integer-valued sensor.
+    ::aidl::android::hardware::automotive::vehicle::StatusCode setIntegerSensor(
+            ::aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex index,
+            int32_t value);
+    // Stores an integer-valued sensor.
+    ::aidl::android::hardware::automotive::vehicle::StatusCode setIntegerSensor(size_t index,
+                                                                                int32_t value);
+    // Stores a float-valued sensor.
+    ::aidl::android::hardware::automotive::vehicle::StatusCode setFloatSensor(
+            ::aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex index,
+            float value);
+    // Stores a float-valued sensor.
+    ::aidl::android::hardware::automotive::vehicle::StatusCode setFloatSensor(size_t index,
+                                                                              float value);
+
+    // Returns a sensor property value using the given DTC.
+    VehiclePropValuePool::RecyclableType getSensorProperty(const std::string& dtc) const;
+
+  private:
+    class BitmaskInVector final {
+      public:
+        explicit BitmaskInVector(size_t numBits = 0);
+        void resize(size_t numBits);
+        ::android::base::Result<bool> get(size_t index) const;
+        ::android::base::Result<void> set(size_t index, bool value);
+
+        const std::vector<uint8_t>& getBitmask() const;
+
+      private:
+        std::vector<uint8_t> mStorage;
+        size_t mNumBits;
+    };
+
+    std::vector<int32_t> mIntegerSensors;
+    std::vector<float> mFloatSensors;
+    BitmaskInVector mSensorsBitmask;
+    std::shared_ptr<VehiclePropValuePool> mValuePool;
+
+    // Returns a vector that contains all integer sensors stored.
+    const std::vector<int32_t>& getIntegerSensors() const;
+    // Returns a vector that contains all float sensors stored.
+    const std::vector<float>& getFloatSensors() const;
+    // Returns a vector that contains a bitmask for all stored sensors.
+    const std::vector<uint8_t>& getSensorsBitmask() const;
+};
+
+}  // namespace obd2frame
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_fake_impl_obd2frame_include_Obd2SensorStore_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp
new file mode 100644
index 0000000..5585fb4
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "FakeObd2Frame.h"
+#include "Obd2SensorStore.h"
+
+#include <PropertyUtils.h>
+#include <VehicleHalTypes.h>
+#include <VehiclePropertyStore.h>
+#include <VehicleUtils.h>
+
+#include <android-base/result.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+namespace obd2frame {
+
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::Obd2CommonIgnitionMonitors;
+using ::aidl::android::hardware::automotive::vehicle::Obd2FuelSystemStatus;
+using ::aidl::android::hardware::automotive::vehicle::Obd2FuelType;
+using ::aidl::android::hardware::automotive::vehicle::Obd2IgnitionMonitorKind;
+using ::aidl::android::hardware::automotive::vehicle::Obd2SecondaryAirStatus;
+using ::aidl::android::hardware::automotive::vehicle::Obd2SparkIgnitionMonitors;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::android::base::Error;
+using ::android::base::Result;
+
+std::unique_ptr<Obd2SensorStore> FakeObd2Frame::fillDefaultObd2Frame(size_t numVendorIntegerSensors,
+                                                                     size_t numVendorFloatSensors) {
+    std::unique_ptr<Obd2SensorStore> sensorStore(new Obd2SensorStore(
+            mPropStore->getValuePool(), numVendorIntegerSensors, numVendorFloatSensors));
+
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_SYSTEM_STATUS,
+                                  toInt(Obd2FuelSystemStatus::CLOSED_LOOP));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
+                                  toInt(Obd2IgnitionMonitorKind::SPARK));
+    sensorStore->setIntegerSensor(
+            DiagnosticIntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
+            toInt(Obd2CommonIgnitionMonitors::COMPONENTS_AVAILABLE) |
+                    toInt(Obd2CommonIgnitionMonitors::MISFIRE_AVAILABLE) |
+                    toInt(Obd2SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE) |
+                    toInt(Obd2SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
+                                  toInt(Obd2SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
+    sensorStore->setIntegerSensor(
+            DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
+    sensorStore->setIntegerSensor(
+            DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_TYPE,
+                                  toInt(Obd2FuelType::GASOLINE));
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ENGINE_RPM, 1250.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::VEHICLE_SPEED, 40.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::TIMING_ADVANCE, 2.5);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::THROTTLE_POSITION, 19.75);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE,
+                                -0.373);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1,
+                                190.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
+
+    return sensorStore;
+}
+
+void FakeObd2Frame::initObd2LiveFrame(const VehiclePropConfig& propConfig) {
+    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+                                            static_cast<size_t>(propConfig.configArray[1]));
+    auto liveObd2Frame = sensorStore->getSensorProperty("");
+    liveObd2Frame->prop = OBD2_LIVE_FRAME;
+
+    mPropStore->writeValue(std::move(liveObd2Frame), /*updateStatus=*/true);
+}
+
+void FakeObd2Frame::initObd2FreezeFrame(const VehiclePropConfig& propConfig) {
+    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+                                            static_cast<size_t>(propConfig.configArray[1]));
+
+    static std::vector<std::string> sampleDtcs = {"P0070", "P0102", "P0123"};
+    for (auto&& dtc : sampleDtcs) {
+        auto freezeFrame = sensorStore->getSensorProperty(dtc);
+        freezeFrame->prop = OBD2_FREEZE_FRAME;
+
+        mPropStore->writeValue(std::move(freezeFrame), /*updateStatus=*/true);
+    }
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeObd2Frame::getObd2FreezeFrame(
+        const VehiclePropValue& requestedPropValue) const {
+    if (requestedPropValue.value.int64Values.size() != 1) {
+        return Error(toInt(StatusCode::INVALID_ARG))
+               << "asked for OBD2_FREEZE_FRAME without valid timestamp";
+    }
+    auto readValuesResult = mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME);
+    if (!readValuesResult.ok()) {
+        return Error(toInt(StatusCode::INTERNAL_ERROR))
+               << "failed to read OBD2_FREEZE_FRAME property: "
+               << readValuesResult.error().message();
+    }
+    if (readValuesResult.value().size() == 0) {
+        // Should no freeze frame be available at the given timestamp, a response of NOT_AVAILABLE
+        // must be returned by the implementation
+        return Error(toInt(StatusCode::NOT_AVAILABLE));
+    }
+    auto timestamp = requestedPropValue.value.int64Values[0];
+    auto readValueResult = mPropStore->readValue(OBD2_FREEZE_FRAME, /*area=*/0, timestamp);
+    if (!readValueResult.ok()) {
+        return Error(toInt(StatusCode::INVALID_ARG))
+               << "asked for OBD2_FREEZE_FRAME at invalid timestamp";
+    }
+    return readValueResult;
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeObd2Frame::getObd2DtcInfo() const {
+    std::vector<int64_t> timestamps;
+    auto result = mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME);
+    if (!result.ok()) {
+        return Error(toInt(StatusCode::INTERNAL_ERROR))
+               << "failed to read OBD2_FREEZE_FRAME property: " << result.error().message();
+    }
+    for (const auto& freezeFrame : result.value()) {
+        timestamps.push_back(freezeFrame->timestamp);
+    }
+    auto outValue =
+            mPropStore->getValuePool()->obtain(VehiclePropertyType::INT64_VEC, timestamps.size());
+    outValue->value.int64Values = timestamps;
+    outValue->prop = OBD2_FREEZE_FRAME_INFO;
+    return outValue;
+}
+
+Result<void> FakeObd2Frame::clearObd2FreezeFrames(const VehiclePropValue& propValue) {
+    if (propValue.value.int64Values.size() == 0) {
+        mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
+        return {};
+    }
+    for (int64_t timestamp : propValue.value.int64Values) {
+        auto result = mPropStore->readValue(OBD2_FREEZE_FRAME, 0, timestamp);
+        if (!result.ok()) {
+            return Error(toInt(StatusCode::INVALID_ARG))
+                   << "asked for OBD2_FREEZE_FRAME at invalid timestamp, error: %s"
+                   << result.error().message();
+        }
+        mPropStore->removeValue(*result.value());
+    }
+    return {};
+}
+
+bool FakeObd2Frame::isDiagnosticProperty(const VehiclePropConfig& propConfig) {
+    return (propConfig.prop == OBD2_LIVE_FRAME || propConfig.prop == OBD2_FREEZE_FRAME ||
+            propConfig.prop == OBD2_FREEZE_FRAME_CLEAR ||
+            propConfig.prop == OBD2_FREEZE_FRAME_INFO);
+}
+
+}  // namespace obd2frame
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/Obd2SensorStore.cpp b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/Obd2SensorStore.cpp
new file mode 100644
index 0000000..4050614
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/Obd2SensorStore.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Obd2SensorStore.h"
+
+#include <VehicleUtils.h>
+
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+namespace obd2frame {
+
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::android::base::Error;
+using ::android::base::Result;
+
+Obd2SensorStore::BitmaskInVector::BitmaskInVector(size_t numBits) {
+    mNumBits = numBits;
+    resize(numBits);
+}
+
+void Obd2SensorStore::BitmaskInVector::resize(size_t numBits) {
+    mNumBits = numBits;
+    mStorage = std::vector<uint8_t>((numBits + 7) / 8, 0);
+}
+
+Result<void> Obd2SensorStore::BitmaskInVector::set(size_t index, bool value) {
+    const size_t byteIndex = index / 8;
+    const size_t bitIndex = index % 8;
+    if (index >= mNumBits) {
+        return Error() << "out of bound";
+    }
+    const uint8_t byte = mStorage[byteIndex];
+    uint8_t newValue = value ? (byte | (1 << bitIndex)) : (byte & ~(1 << bitIndex));
+    mStorage[byteIndex] = newValue;
+    return {};
+}
+
+Result<bool> Obd2SensorStore::BitmaskInVector::get(size_t index) const {
+    const size_t byteIndex = index / 8;
+    const size_t bitIndex = index % 8;
+    if (index >= mNumBits) {
+        return Error() << "out of bound";
+    }
+    const uint8_t byte = mStorage[byteIndex];
+    return (byte & (1 << bitIndex)) != 0;
+}
+
+const std::vector<uint8_t>& Obd2SensorStore::BitmaskInVector::getBitmask() const {
+    return mStorage;
+}
+
+Obd2SensorStore::Obd2SensorStore(std::shared_ptr<VehiclePropValuePool> valuePool,
+                                 size_t numVendorIntegerSensors, size_t numVendorFloatSensors)
+    : mValuePool(valuePool) {
+    const size_t numSystemIntegerSensors = getLastIndex<DiagnosticIntegerSensorIndex>() + 1;
+    const size_t numSystemFloatSensors = getLastIndex<DiagnosticFloatSensorIndex>() + 1;
+    mIntegerSensors = std::vector<int32_t>(numSystemIntegerSensors + numVendorIntegerSensors, 0);
+    mFloatSensors = std::vector<float>(numSystemFloatSensors + numVendorFloatSensors, 0);
+    mSensorsBitmask.resize(mIntegerSensors.size() + mFloatSensors.size());
+}
+
+StatusCode Obd2SensorStore::setIntegerSensor(DiagnosticIntegerSensorIndex index, int32_t value) {
+    return setIntegerSensor(toInt(index), value);
+}
+StatusCode Obd2SensorStore::setFloatSensor(DiagnosticFloatSensorIndex index, float value) {
+    return setFloatSensor(toInt(index), value);
+}
+
+StatusCode Obd2SensorStore::setIntegerSensor(size_t index, int32_t value) {
+    if (index >= mIntegerSensors.size()) {
+        ALOGE("failed to set integer sensor: OOB");
+        return StatusCode::INVALID_ARG;
+    }
+    mIntegerSensors[index] = value;
+    if (auto result = mSensorsBitmask.set(index, true); !result.ok()) {
+        ALOGE("failed to set integer sensor: %s", result.error().message().c_str());
+        return StatusCode::INVALID_ARG;
+    }
+    return StatusCode::OK;
+}
+
+StatusCode Obd2SensorStore::setFloatSensor(size_t index, float value) {
+    if (index >= mFloatSensors.size()) {
+        ALOGE("failed to set integer sensor: OOB");
+        return StatusCode::INVALID_ARG;
+    }
+    mFloatSensors[index] = value;
+    if (auto result = mSensorsBitmask.set(index + mIntegerSensors.size(), true); !result.ok()) {
+        ALOGE("failed to set float sensor: %s", result.error().message().c_str());
+        return StatusCode::INVALID_ARG;
+    }
+    return StatusCode::OK;
+}
+
+const std::vector<int32_t>& Obd2SensorStore::getIntegerSensors() const {
+    return mIntegerSensors;
+}
+
+const std::vector<float>& Obd2SensorStore::getFloatSensors() const {
+    return mFloatSensors;
+}
+
+const std::vector<uint8_t>& Obd2SensorStore::getSensorsBitmask() const {
+    return mSensorsBitmask.getBitmask();
+}
+
+VehiclePropValuePool::RecyclableType Obd2SensorStore::getSensorProperty(
+        const std::string& dtc) const {
+    auto propValue = mValuePool->obtain(VehiclePropertyType::MIXED);
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values = getIntegerSensors();
+    propValue->value.floatValues = getFloatSensors();
+    propValue->value.byteValues = getSensorsBitmask();
+    propValue->value.stringValue = dtc;
+    return propValue;
+}
+
+}  // namespace obd2frame
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Android.bp
new file mode 100644
index 0000000..55b8c93
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Android.bp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "FakeObd2FrameTest",
+    vendor: true,
+    srcs: ["*.cpp"],
+    defaults: ["VehicleHalDefaults"],
+    static_libs: [
+        "FakeObd2Frame",
+        "VehicleHalUtils",
+    ],
+    test_suites: ["device-tests"],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp
new file mode 100644
index 0000000..54ec1b2
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/FakeObd2FrameTest.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FakeObd2Frame.h"
+
+#include <PropertyUtils.h>
+#include <VehicleObjectPool.h>
+#include <VehiclePropertyStore.h>
+#include <gtest/gtest.h>
+#include <utils/SystemClock.h>
+
+#include <set>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+namespace obd2frame {
+
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+class FakeObd2FrameTest : public ::testing::Test {
+  protected:
+    void SetUp() override {
+        std::shared_ptr<VehiclePropValuePool> valuePool = std::make_shared<VehiclePropValuePool>();
+        mPropertyStore = std::make_shared<VehiclePropertyStore>(valuePool);
+        mObd2Frame = std::make_unique<FakeObd2Frame>(mPropertyStore);
+
+        mPropertyStore->registerProperty(getObd2LiveFrameConfig());
+        mPropertyStore->registerProperty(
+                getObd2FreezeFrameConfig(),
+                [](const VehiclePropValue& propValue) { return propValue.timestamp; });
+        mPropertyStore->registerProperty(getObd2FreezeFrameInfoConfig());
+    }
+
+    VehiclePropConfig getObd2LiveFrameConfig() {
+        return VehiclePropConfig{.prop = OBD2_LIVE_FRAME,
+                                 .access = VehiclePropertyAccess::READ,
+                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                                 .configArray = {1, 1}};
+    }
+
+    VehiclePropConfig getObd2FreezeFrameConfig() {
+        return VehiclePropConfig{.prop = OBD2_FREEZE_FRAME,
+                                 .access = VehiclePropertyAccess::READ,
+                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                                 .configArray = {0, 0}};
+    }
+
+    VehiclePropConfig getObd2FreezeFrameInfoConfig() {
+        return VehiclePropConfig{.prop = OBD2_FREEZE_FRAME_INFO,
+                                 .access = VehiclePropertyAccess::READ,
+                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE};
+    }
+
+    FakeObd2Frame* getFakeObd2Frame() { return mObd2Frame.get(); }
+
+    VehiclePropertyStore* getPropertyStore() { return mPropertyStore.get(); }
+
+  private:
+    std::unique_ptr<FakeObd2Frame> mObd2Frame;
+    std::shared_ptr<VehiclePropertyStore> mPropertyStore;
+};
+
+TEST_F(FakeObd2FrameTest, testIsDiagnosticPropertyTrue) {
+    for (auto prop : std::vector<int32_t>({
+                 OBD2_LIVE_FRAME,
+                 OBD2_FREEZE_FRAME,
+                 OBD2_FREEZE_FRAME_CLEAR,
+                 OBD2_FREEZE_FRAME_INFO,
+         })) {
+        EXPECT_TRUE(FakeObd2Frame::isDiagnosticProperty(VehiclePropConfig{
+                .prop = prop,
+        }));
+    }
+}
+
+TEST_F(FakeObd2FrameTest, testIsDiagnosticPropertyFalse) {
+    ASSERT_FALSE(FakeObd2Frame::isDiagnosticProperty(VehiclePropConfig{
+            .prop = toInt(VehicleProperty::INFO_VIN),
+    }));
+}
+
+TEST_F(FakeObd2FrameTest, testInitObd2LiveFrame) {
+    int64_t timestamp = elapsedRealtimeNano();
+
+    getFakeObd2Frame()->initObd2LiveFrame(getObd2LiveFrameConfig());
+
+    auto result = getPropertyStore()->readValue(OBD2_LIVE_FRAME);
+
+    ASSERT_TRUE(result.ok());
+    auto& value = result.value();
+
+    EXPECT_GE(value->timestamp, timestamp);
+    EXPECT_EQ(value->value.stringValue, "");
+    EXPECT_EQ(value->value.int32Values.size(), static_cast<size_t>(33));
+    EXPECT_EQ(value->value.floatValues.size(), static_cast<size_t>(72));
+}
+
+TEST_F(FakeObd2FrameTest, testInitFreezeFrame) {
+    getFakeObd2Frame()->initObd2FreezeFrame(getObd2FreezeFrameConfig());
+
+    auto result = getPropertyStore()->readValuesForProperty(OBD2_FREEZE_FRAME);
+
+    ASSERT_TRUE(result.ok());
+    ASSERT_EQ(result.value().size(), static_cast<size_t>(3));
+}
+
+TEST_F(FakeObd2FrameTest, testGetObd2DtcInfo) {
+    getFakeObd2Frame()->initObd2FreezeFrame(getObd2FreezeFrameConfig());
+
+    auto result = getFakeObd2Frame()->getObd2DtcInfo();
+
+    ASSERT_TRUE(result.ok());
+    EXPECT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO);
+    EXPECT_EQ(result.value()->value.int64Values.size(), static_cast<size_t>(3));
+}
+
+TEST_F(FakeObd2FrameTest, testGetObd2FreezeFrame) {
+    getFakeObd2Frame()->initObd2FreezeFrame(getObd2FreezeFrameConfig());
+
+    auto result = getFakeObd2Frame()->getObd2DtcInfo();
+
+    ASSERT_TRUE(result.ok());
+    ASSERT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO);
+    ASSERT_EQ(result.value()->value.int64Values.size(), static_cast<size_t>(3));
+
+    std::set<std::string> dtcs;
+
+    for (int64_t timestamp : result.value()->value.int64Values) {
+        auto freezeFrameResult = getFakeObd2Frame()->getObd2FreezeFrame(VehiclePropValue{
+                .value.int64Values = {timestamp},
+        });
+
+        ASSERT_TRUE(freezeFrameResult.ok());
+
+        dtcs.insert(freezeFrameResult.value()->value.stringValue);
+    }
+
+    ASSERT_EQ(dtcs, std::set<std::string>({"P0070", "P0102", "P0123"}));
+}
+
+TEST_F(FakeObd2FrameTest, testClearObd2FreezeFrameAll) {
+    getFakeObd2Frame()->initObd2FreezeFrame(getObd2FreezeFrameConfig());
+
+    auto result = getFakeObd2Frame()->getObd2DtcInfo();
+
+    ASSERT_TRUE(result.ok());
+    ASSERT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO);
+    ASSERT_EQ(result.value()->value.int64Values.size(), static_cast<size_t>(3));
+
+    ASSERT_TRUE(getFakeObd2Frame()->clearObd2FreezeFrames(VehiclePropValue{}).ok());
+
+    result = getFakeObd2Frame()->getObd2DtcInfo();
+
+    ASSERT_TRUE(result.ok());
+    EXPECT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO);
+    EXPECT_EQ(result.value()->value.int64Values.size(), static_cast<size_t>(0));
+}
+
+TEST_F(FakeObd2FrameTest, testClearObd2FreezeFrameByTimestamp) {
+    getFakeObd2Frame()->initObd2FreezeFrame(getObd2FreezeFrameConfig());
+
+    auto result = getFakeObd2Frame()->getObd2DtcInfo();
+
+    ASSERT_TRUE(result.ok());
+    ASSERT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO);
+    ASSERT_EQ(result.value()->value.int64Values.size(), static_cast<size_t>(3));
+
+    ASSERT_TRUE(getFakeObd2Frame()
+                        ->clearObd2FreezeFrames(VehiclePropValue{
+                                .value.int64Values = {result.value()->value.int64Values[0],
+                                                      result.value()->value.int64Values[1]}})
+                        .ok());
+
+    result = getFakeObd2Frame()->getObd2DtcInfo();
+
+    ASSERT_TRUE(result.ok());
+    EXPECT_EQ(result.value()->prop, OBD2_FREEZE_FRAME_INFO);
+    EXPECT_EQ(result.value()->value.int64Values.size(), static_cast<size_t>(1));
+}
+
+}  // namespace obd2frame
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp
new file mode 100644
index 0000000..23ea51d
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/test/Obd2SensorStoreTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Obd2SensorStore.h"
+
+#include <VehicleUtils.h>
+
+#include <gtest/gtest.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+namespace obd2frame {
+
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+
+TEST(Obd2SensorStoreTest, testObd2SensorStore) {
+    int64_t timestamp = elapsedRealtimeNano();
+    std::shared_ptr<VehiclePropValuePool> valuePool = std::make_shared<VehiclePropValuePool>();
+    Obd2SensorStore sensorStore(valuePool, 1, 1);
+
+    DiagnosticIntegerSensorIndex systemIntSensorIndex =
+            DiagnosticIntegerSensorIndex::IGNITION_MONITORS_SUPPORTED;
+    size_t vendorIntSensorIndex = Obd2SensorStore::getLastIndex<DiagnosticIntegerSensorIndex>() + 1;
+    DiagnosticFloatSensorIndex systemFloatSensorIndex =
+            DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1;
+    size_t vendorFloatSensorIndex = Obd2SensorStore::getLastIndex<DiagnosticFloatSensorIndex>() + 1;
+    // Four 1s in all the bits.
+    std::vector<uint8_t> bitMask = {0x4, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0,
+                                    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1};
+
+    ASSERT_EQ(sensorStore.setIntegerSensor(systemIntSensorIndex, 1), StatusCode::OK);
+    ASSERT_EQ(sensorStore.setIntegerSensor(vendorIntSensorIndex, 2), StatusCode::OK);
+    ASSERT_EQ(sensorStore.setFloatSensor(systemFloatSensorIndex, 3.0), StatusCode::OK);
+    ASSERT_EQ(sensorStore.setFloatSensor(vendorFloatSensorIndex, 4.0), StatusCode::OK);
+
+    std::string dtc = "dtc";
+    auto propValue = sensorStore.getSensorProperty(dtc);
+
+    ASSERT_GE(propValue->timestamp, timestamp);
+    ASSERT_EQ(propValue->value.int32Values[toInt(systemIntSensorIndex)], 1);
+    ASSERT_EQ(propValue->value.int32Values[vendorIntSensorIndex], 2);
+    ASSERT_EQ(propValue->value.floatValues[toInt(systemFloatSensorIndex)], 3.0);
+    ASSERT_EQ(propValue->value.floatValues[vendorFloatSensorIndex], 4.0);
+    ASSERT_EQ(propValue->value.byteValues, bitMask);
+    ASSERT_EQ(propValue->value.stringValue, dtc);
+}
+
+TEST(Obd2SensorStoreTest, testIndexOOB) {
+    std::shared_ptr<VehiclePropValuePool> valuePool = std::make_shared<VehiclePropValuePool>();
+    Obd2SensorStore sensorStore(valuePool, 1, 1);
+
+    EXPECT_EQ(sensorStore.setIntegerSensor(
+                      Obd2SensorStore::getLastIndex<DiagnosticIntegerSensorIndex>() + 2, 1),
+              StatusCode::INVALID_ARG);
+    EXPECT_EQ(sensorStore.setIntegerSensor(static_cast<size_t>(-1), 1), StatusCode::INVALID_ARG);
+    EXPECT_EQ(sensorStore.setFloatSensor(
+                      Obd2SensorStore::getLastIndex<DiagnosticFloatSensorIndex>() + 2, 1.0),
+              StatusCode::INVALID_ARG);
+    EXPECT_EQ(sensorStore.setFloatSensor(static_cast<size_t>(-1), 1.0), StatusCode::INVALID_ARG);
+}
+
+}  // namespace obd2frame
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/userhal/Android.bp
new file mode 100644
index 0000000..2e95531
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/Android.bp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library {
+    name: "FakeUserHal",
+    vendor: true,
+    srcs: ["src/*.cpp"],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    defaults: ["VehicleHalDefaults"],
+    static_libs: [
+        "VehicleHalUtils",
+    ],
+    export_static_lib_headers: ["VehicleHalUtils"],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
new file mode 100644
index 0000000..1424c81
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_fake_impl_userhal_include_FakeUserHal_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_FakeUserHal_H_
+
+#include <android-base/format.h>
+#include <android-base/result.h>
+#include <android-base/thread_annotations.h>
+
+#include <VehicleHalTypes.h>
+#include <VehicleObjectPool.h>
+
+#include <memory>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+constexpr char kUserHalDumpOption[] = "--user-hal";
+
+// Class used to emulate a real User HAL behavior through lshal debug requests.
+class FakeUserHal final {
+  public:
+    explicit FakeUserHal(std::shared_ptr<VehiclePropValuePool> valuePool) : mValuePool(valuePool) {}
+
+    ~FakeUserHal() = default;
+
+    // Checks if the emulator can handle the property.
+    static bool isSupported(int32_t prop);
+
+    // Lets the emulator set the property.
+    //
+    // @return updated property and StatusCode
+    android::base::Result<VehiclePropValuePool::RecyclableType> onSetProperty(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+
+    // Gets the property value from the emulator.
+    //
+    // @return property value and StatusCode
+    android::base::Result<VehiclePropValuePool::RecyclableType> onGetProperty(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
+
+    // Shows the User HAL emulation help.
+    std::string showDumpHelp() const;
+
+    // Dump its contents.
+    std::string dump(std::string indent) const;
+
+  private:
+    const std::shared_ptr<VehiclePropValuePool> mValuePool;
+    mutable std::mutex mLock;
+    VehiclePropValuePool::RecyclableType mInitialUserResponseFromCmd GUARDED_BY(mLock);
+    VehiclePropValuePool::RecyclableType mSwitchUserResponseFromCmd GUARDED_BY(mLock);
+    VehiclePropValuePool::RecyclableType mCreateUserResponseFromCmd GUARDED_BY(mLock);
+    VehiclePropValuePool::RecyclableType mSetUserIdentificationAssociationResponseFromCmd
+            GUARDED_BY(mLock);
+
+    // INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
+    // indicating what the initial user should be.
+    //
+    // During normal circumstances, the emulator will reply right away, passing a response if
+    // InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which
+    // user to boot).
+    //
+    // But during development / testing, the behavior can be changed using lshal dump, which must
+    // use the areaId to indicate what should happen next.
+    //
+    // So, the behavior of set(INITIAL_USER_INFO) is:
+    //
+    // - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called
+    // by lshal).
+    // - else if mInitialUserResponseFromCmd is not set, return a response with the same request id
+    // and InitialUserInfoResponseAction::DEFAULT
+    // - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
+    // - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
+    // - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can
+    // test this error scenario)
+    // - if it's 3, then don't send a property change (so Android can emulate a timeout)
+    android::base::Result<VehiclePropValuePool::RecyclableType> onSetInitialUserInfoResponse(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+
+    // Used to emulate SWITCH_USER - see onSetInitialUserInfoResponse() for usage.
+    android::base::Result<VehiclePropValuePool::RecyclableType> onSetSwitchUserResponse(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+
+    // Used to emulate CREATE_USER - see onSetInitialUserInfoResponse() for usage.
+    android::base::Result<VehiclePropValuePool::RecyclableType> onSetCreateUserResponse(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+
+    // Used to emulate set USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
+    // usage.
+    android::base::Result<VehiclePropValuePool::RecyclableType> onSetUserIdentificationAssociation(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+
+    // Used to emulate get USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
+    // usage.
+    android::base::Result<VehiclePropValuePool::RecyclableType> onGetUserIdentificationAssociation(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
+
+    // Creates a default USER_IDENTIFICATION_ASSOCIATION when it was not set by lshal.
+    static android::base::Result<VehiclePropValuePool::RecyclableType>
+    defaultUserIdentificationAssociation(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& request);
+
+    android::base::Result<VehiclePropValuePool::RecyclableType> sendUserHalResponse(
+            VehiclePropValuePool::RecyclableType response, int32_t requestId);
+};
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_FakeUserHal_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalHelper.h b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalHelper.h
new file mode 100644
index 0000000..5be13be
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalHelper.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalHelper_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalHelper_H_
+
+#include <UserHalTypes.h>
+#include <VehicleHalTypes.h>
+#include <VehicleObjectPool.h>
+#include <android-base/result.h>
+
+#include <functional>
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+namespace user_hal_helper {
+
+// Verify whether the |value| can be casted to the type |T| and return the casted value on success.
+// Otherwise, return the error.
+template <typename T>
+::android::base::Result<T> verifyAndCast(int32_t value);
+
+// Below functions parse VehiclePropValues to the respective User HAL request structs. On success,
+// these functions return the User HAL struct. Otherwise, they return the error.
+::android::base::Result<::aidl::android::hardware::automotive::vehicle::InitialUserInfoRequest>
+toInitialUserInfoRequest(
+        const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+::android::base::Result<::aidl::android::hardware::automotive::vehicle::SwitchUserRequest>
+toSwitchUserRequest(
+        const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+::android::base::Result<::aidl::android::hardware::automotive::vehicle::CreateUserRequest>
+toCreateUserRequest(
+        const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+::android::base::Result<::aidl::android::hardware::automotive::vehicle::RemoveUserRequest>
+toRemoveUserRequest(
+        const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+::android::base::Result<
+        ::aidl::android::hardware::automotive::vehicle::UserIdentificationGetRequest>
+toUserIdentificationGetRequest(
+        const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+::android::base::Result<
+        ::aidl::android::hardware::automotive::vehicle::UserIdentificationSetRequest>
+toUserIdentificationSetRequest(
+        const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+
+// Below functions convert the User HAL structs to VehiclePropValues. On success, these functions
+// return the pointer to VehiclePropValue. Otherwise, they return the error.
+::android::base::Result<VehiclePropValuePool::RecyclableType> toVehiclePropValue(
+        VehiclePropValuePool& pool,
+        const ::aidl::android::hardware::automotive::vehicle::SwitchUserRequest& request);
+VehiclePropValuePool::RecyclableType toVehiclePropValue(
+        VehiclePropValuePool& pool,
+        const ::aidl::android::hardware::automotive::vehicle::InitialUserInfoResponse& response);
+VehiclePropValuePool::RecyclableType toVehiclePropValue(
+        VehiclePropValuePool& pool,
+        const ::aidl::android::hardware::automotive::vehicle::SwitchUserResponse& response);
+VehiclePropValuePool::RecyclableType toVehiclePropValue(
+        VehiclePropValuePool& pool,
+        const ::aidl::android::hardware::automotive::vehicle::CreateUserResponse& response);
+VehiclePropValuePool::RecyclableType toVehiclePropValue(
+        VehiclePropValuePool& pool,
+        const ::aidl::android::hardware::automotive::vehicle::UserIdentificationResponse& response);
+
+}  // namespace user_hal_helper
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalHelper_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalTypes.h b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalTypes.h
new file mode 100644
index 0000000..b5e17b3
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/UserHalTypes.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.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalTypes_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalTypes_H_
+
+#include <aidl/android/hardware/automotive/vehicle/CreateUserRequest.h>
+#include <aidl/android/hardware/automotive/vehicle/CreateUserResponse.h>
+#include <aidl/android/hardware/automotive/vehicle/CreateUserStatus.h>
+#include <aidl/android/hardware/automotive/vehicle/InitialUserInfoRequest.h>
+#include <aidl/android/hardware/automotive/vehicle/InitialUserInfoRequestType.h>
+#include <aidl/android/hardware/automotive/vehicle/InitialUserInfoResponse.h>
+#include <aidl/android/hardware/automotive/vehicle/RemoveUserRequest.h>
+#include <aidl/android/hardware/automotive/vehicle/SwitchUserMessageType.h>
+#include <aidl/android/hardware/automotive/vehicle/SwitchUserRequest.h>
+#include <aidl/android/hardware/automotive/vehicle/SwitchUserResponse.h>
+#include <aidl/android/hardware/automotive/vehicle/SwitchUserStatus.h>
+#include <aidl/android/hardware/automotive/vehicle/UserIdentificationGetRequest.h>
+#include <aidl/android/hardware/automotive/vehicle/UserIdentificationResponse.h>
+#include <aidl/android/hardware/automotive/vehicle/UserIdentificationSetRequest.h>
+#include <aidl/android/hardware/automotive/vehicle/UserInfo.h>
+#include <aidl/android/hardware/automotive/vehicle/UsersInfo.h>
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_UserHalTypes_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
new file mode 100644
index 0000000..9b60053
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
@@ -0,0 +1,374 @@
+/*
+ * 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 "FakeUserHal"
+
+#include "FakeUserHal.h"
+
+#include "UserHalHelper.h"
+
+#include <VehicleUtils.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::CreateUserResponse;
+using ::aidl::android::hardware::automotive::vehicle::CreateUserStatus;
+using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoResponse;
+using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoResponseAction;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::SwitchUserMessageType;
+using ::aidl::android::hardware::automotive::vehicle::SwitchUserResponse;
+using ::aidl::android::hardware::automotive::vehicle::SwitchUserStatus;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::android::base::Error;
+using ::android::base::Result;
+
+constexpr int32_t INITIAL_USER_INFO = toInt(VehicleProperty::INITIAL_USER_INFO);
+constexpr int32_t SWITCH_USER = toInt(VehicleProperty::SWITCH_USER);
+constexpr int32_t CREATE_USER = toInt(VehicleProperty::CREATE_USER);
+constexpr int32_t REMOVE_USER = toInt(VehicleProperty::REMOVE_USER);
+constexpr int32_t USER_IDENTIFICATION_ASSOCIATION =
+        toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+
+Result<int32_t> getRequestId(const VehiclePropValue& value) {
+    if (value.value.int32Values.size() < 1) {
+        return Error(toInt(StatusCode::INVALID_ARG))
+               << "no int32Values on property: " << value.toString();
+    }
+    return value.value.int32Values[0];
+}
+
+Result<SwitchUserMessageType> getSwitchUserMessageType(const VehiclePropValue& value) {
+    if (value.value.int32Values.size() < 2) {
+        return Error(toInt(StatusCode::INVALID_ARG))
+               << "missing switch user message type on property: " << value.toString();
+    }
+    return user_hal_helper::verifyAndCast<SwitchUserMessageType>(value.value.int32Values[1]);
+}
+
+}  // namespace
+
+bool FakeUserHal::isSupported(int32_t prop) {
+    switch (prop) {
+        case INITIAL_USER_INFO:
+        case SWITCH_USER:
+        case CREATE_USER:
+        case REMOVE_USER:
+        case USER_IDENTIFICATION_ASSOCIATION:
+            return true;
+        default:
+            return false;
+    }
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeUserHal::onSetProperty(
+        const VehiclePropValue& value) {
+    ALOGV("onSetProperty(): %s", value.toString().c_str());
+
+    switch (value.prop) {
+        case INITIAL_USER_INFO:
+            return onSetInitialUserInfoResponse(value);
+        case SWITCH_USER:
+            return onSetSwitchUserResponse(value);
+        case CREATE_USER:
+            return onSetCreateUserResponse(value);
+        case REMOVE_USER:
+            ALOGI("REMOVE_USER is FYI only, nothing to do...");
+            return nullptr;
+        case USER_IDENTIFICATION_ASSOCIATION:
+            return onSetUserIdentificationAssociation(value);
+        default:
+            return Error(toInt(StatusCode::INVALID_ARG))
+                   << "Unsupported property: " << value.toString();
+    }
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeUserHal::onGetProperty(
+        const VehiclePropValue& value) const {
+    ALOGV("onGetProperty(%s)", value.toString().c_str());
+    switch (value.prop) {
+        case INITIAL_USER_INFO:
+        case SWITCH_USER:
+        case CREATE_USER:
+        case REMOVE_USER:
+            ALOGE("onGetProperty(): %d is only supported on SET", value.prop);
+            return Error(toInt(StatusCode::INVALID_ARG)) << "only supported on SET";
+        case USER_IDENTIFICATION_ASSOCIATION:
+            return onGetUserIdentificationAssociation(value);
+        default:
+            ALOGE("onGetProperty(): %d is not supported", value.prop);
+            return Error(toInt(StatusCode::INVALID_ARG)) << "not supported by User HAL";
+    }
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeUserHal::onGetUserIdentificationAssociation(
+        const VehiclePropValue& value) const {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    if (mSetUserIdentificationAssociationResponseFromCmd == nullptr) {
+        return defaultUserIdentificationAssociation(value);
+    }
+    ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s",
+          mSetUserIdentificationAssociationResponseFromCmd->toString().c_str());
+    auto newValue = mValuePool->obtain(*mSetUserIdentificationAssociationResponseFromCmd);
+    auto requestId = getRequestId(value);
+    if (requestId.ok()) {
+        // Must use the same requestId
+        newValue->value.int32Values[0] = *requestId;
+    } else {
+        ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s", value.toString().c_str());
+        return requestId.error();
+    }
+    return newValue;
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeUserHal::onSetInitialUserInfoResponse(
+        const VehiclePropValue& value) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(INITIAL_USER_INFO): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
+    }
+
+    if (value.areaId != 0) {
+        ALOGD("set(INITIAL_USER_INFO) called from lshal; storing it: %s", value.toString().c_str());
+        mInitialUserResponseFromCmd = mValuePool->obtain(value);
+        return nullptr;
+    }
+
+    ALOGD("set(INITIAL_USER_INFO) called from Android: %s", value.toString().c_str());
+    if (mInitialUserResponseFromCmd != nullptr) {
+        ALOGI("replying INITIAL_USER_INFO with lshal value: %s",
+              mInitialUserResponseFromCmd->toString().c_str());
+        return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), *requestId);
+    }
+
+    // Returns default response
+    auto updatedValue = user_hal_helper::toVehiclePropValue(
+            *mValuePool, InitialUserInfoResponse{
+                                 .requestId = *requestId,
+                                 .action = InitialUserInfoResponseAction::DEFAULT,
+                         });
+    ALOGI("no lshal response; replying with InitialUserInfoResponseAction::DEFAULT: %s",
+          updatedValue->toString().c_str());
+    return updatedValue;
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeUserHal::onSetSwitchUserResponse(
+        const VehiclePropValue& value) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(SWITCH_USER): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
+    }
+
+    auto messageType = getSwitchUserMessageType(value);
+    if (!messageType.ok()) {
+        ALOGE("Failed to get messageType on set(SWITCH_USER): %s",
+              messageType.error().message().c_str());
+        return messageType.error();
+    }
+
+    if (value.areaId != 0) {
+        if (*messageType == SwitchUserMessageType::VEHICLE_REQUEST) {
+            // User HAL can also request a user switch, so we need to check it first
+            ALOGD("set(SWITCH_USER) called from lshal to emulate a vehicle request: %s",
+                  value.toString().c_str());
+            return mValuePool->obtain(value);
+        }
+        // Otherwise, we store it
+        ALOGD("set(SWITCH_USER) called from lshal; storing it: %s", value.toString().c_str());
+        mSwitchUserResponseFromCmd = mValuePool->obtain(value);
+        return nullptr;
+    }
+    ALOGD("set(SWITCH_USER) called from Android: %s", value.toString().c_str());
+
+    if (mSwitchUserResponseFromCmd != nullptr) {
+        ALOGI("replying SWITCH_USER with lshal value:  %s",
+              mSwitchUserResponseFromCmd->toString().c_str());
+        return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), *requestId);
+    }
+
+    if (*messageType == SwitchUserMessageType::LEGACY_ANDROID_SWITCH ||
+        *messageType == SwitchUserMessageType::ANDROID_POST_SWITCH) {
+        ALOGI("request is %s; ignoring it", toString(*messageType).c_str());
+        return nullptr;
+    }
+
+    // Returns default response
+    auto updatedValue = user_hal_helper::toVehiclePropValue(
+            *mValuePool, SwitchUserResponse{
+                                 .requestId = *requestId,
+                                 .messageType = SwitchUserMessageType::VEHICLE_RESPONSE,
+                                 .status = SwitchUserStatus::SUCCESS,
+                         });
+    ALOGI("no lshal response; replying with VEHICLE_RESPONSE / SUCCESS: %s",
+          updatedValue->toString().c_str());
+    return updatedValue;
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeUserHal::onSetCreateUserResponse(
+        const VehiclePropValue& value) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(CREATE_USER): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
+    }
+
+    if (value.areaId != 0) {
+        ALOGD("set(CREATE_USER) called from lshal; storing it: %s", value.toString().c_str());
+        mCreateUserResponseFromCmd = mValuePool->obtain(value);
+        return nullptr;
+    }
+    ALOGD("set(CREATE_USER) called from Android: %s", value.toString().c_str());
+
+    if (mCreateUserResponseFromCmd != nullptr) {
+        ALOGI("replying CREATE_USER with lshal value:  %s",
+              mCreateUserResponseFromCmd->toString().c_str());
+        return sendUserHalResponse(std::move(mCreateUserResponseFromCmd), *requestId);
+    }
+
+    // Returns default response
+    auto updatedValue = user_hal_helper::toVehiclePropValue(
+            *mValuePool, CreateUserResponse{
+                                 .requestId = *requestId,
+                                 .status = CreateUserStatus::SUCCESS,
+                         });
+    ALOGI("no lshal response; replying with SUCCESS: %s", updatedValue->toString().c_str());
+    return updatedValue;
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeUserHal::onSetUserIdentificationAssociation(
+        const VehiclePropValue& value) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(USER_IDENTIFICATION_ASSOCIATION): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
+    }
+
+    if (value.areaId != 0) {
+        ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from lshal; storing it: %s",
+              value.toString().c_str());
+        mSetUserIdentificationAssociationResponseFromCmd = mValuePool->obtain(value);
+        return nullptr;
+    }
+    ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from Android: %s", value.toString().c_str());
+
+    if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
+        ALOGI("replying USER_IDENTIFICATION_ASSOCIATION with lshal value:  %s",
+              mSetUserIdentificationAssociationResponseFromCmd->toString().c_str());
+        // Not moving response so it can be used on GET requests
+        auto copy = mValuePool->obtain(*mSetUserIdentificationAssociationResponseFromCmd);
+        return sendUserHalResponse(std::move(copy), *requestId);
+    }
+    // Returns default response
+    return defaultUserIdentificationAssociation(value);
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeUserHal::defaultUserIdentificationAssociation(
+        const VehiclePropValue& request) {
+    // TODO(b/159498909): return a response with NOT_ASSOCIATED_ANY_USER for all requested types
+    ALOGE("no lshal response for %s; replying with NOT_AVAILABLE", request.toString().c_str());
+    return Error(toInt(StatusCode::NOT_AVAILABLE)) << "not set by lshal";
+}
+
+Result<VehiclePropValuePool::RecyclableType> FakeUserHal::sendUserHalResponse(
+        VehiclePropValuePool::RecyclableType response, int32_t requestId) {
+    switch (response->areaId) {
+        case 1:
+            ALOGD("returning response with right request id");
+            response->value.int32Values[0] = requestId;
+            break;
+        case 2:
+            ALOGD("returning response with wrong request id");
+            response->value.int32Values[0] = -requestId;
+            break;
+        case 3:
+            ALOGD("not generating a property change event because of lshal prop: %s",
+                  response->toString().c_str());
+            return Error(toInt(StatusCode::NOT_AVAILABLE))
+                   << "not generating a property change event because of lshal prop: "
+                   << response->toString();
+        default:
+            ALOGE("invalid action on lshal response: %s", response->toString().c_str());
+            return Error(toInt(StatusCode::INTERNAL_ERROR))
+                   << "invalid action on lshal response: " << response->toString();
+    }
+
+    ALOGD("updating property to: %s", response->toString().c_str());
+    return response;
+}
+
+std::string FakeUserHal::showDumpHelp() const {
+    return fmt::format("{}: dumps state used for user management\n", kUserHalDumpOption);
+}
+
+std::string FakeUserHal::dump(std::string indent) const {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    std::string info;
+    if (mInitialUserResponseFromCmd != nullptr) {
+        info += fmt::format("{}InitialUserInfo response: {}\n", indent,
+                            mInitialUserResponseFromCmd->toString());
+    } else {
+        info += fmt::format("{}No InitialUserInfo response\n", indent);
+    }
+    if (mSwitchUserResponseFromCmd != nullptr) {
+        info += fmt::format("{}SwitchUser response: {}\n", indent,
+                            mSwitchUserResponseFromCmd->toString());
+    } else {
+        info += fmt::format("{}No SwitchUser response\n", indent);
+    }
+    if (mCreateUserResponseFromCmd != nullptr) {
+        info += fmt::format("{}CreateUser response: {}\n", indent,
+                            mCreateUserResponseFromCmd->toString());
+    } else {
+        info += fmt::format("{}No CreateUser response\n", indent);
+    }
+    if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
+        info += fmt::format("{}SetUserIdentificationAssociation response: {}\n", indent,
+                            mSetUserIdentificationAssociationResponseFromCmd->toString());
+    } else {
+        info += fmt::format("{}No SetUserIdentificationAssociation response\n", indent);
+    }
+    return info;
+}
+
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/UserHalHelper.cpp b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/UserHalHelper.cpp
new file mode 100644
index 0000000..4fd93ae
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/UserHalHelper.cpp
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "UserHalHelper"
+
+#include "UserHalHelper.h"
+
+#include <VehicleUtils.h>
+#include <log/log.h>
+#include <utils/SystemClock.h>
+
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+namespace user_hal_helper {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::CreateUserRequest;
+using ::aidl::android::hardware::automotive::vehicle::CreateUserResponse;
+using ::aidl::android::hardware::automotive::vehicle::CreateUserStatus;
+using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoRequest;
+using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoRequestType;
+using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoResponse;
+using ::aidl::android::hardware::automotive::vehicle::RemoveUserRequest;
+using ::aidl::android::hardware::automotive::vehicle::SwitchUserMessageType;
+using ::aidl::android::hardware::automotive::vehicle::SwitchUserRequest;
+using ::aidl::android::hardware::automotive::vehicle::SwitchUserResponse;
+using ::aidl::android::hardware::automotive::vehicle::SwitchUserStatus;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationAssociationSetValue;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationAssociationType;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationGetRequest;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationResponse;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationSetAssociation;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationSetRequest;
+using ::aidl::android::hardware::automotive::vehicle::UserInfo;
+using ::aidl::android::hardware::automotive::vehicle::UsersInfo;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::android::base::Error;
+using ::android::base::Result;
+
+constexpr const char kSeparator[] = "||";
+constexpr size_t kNumFieldsPerUserInfo = 2;
+constexpr size_t kNumFieldsPerSetAssociation = 2;
+
+Result<void> verifyPropValue(const VehiclePropValue& propValue, VehicleProperty vehicleProperty,
+                             size_t minInt32Values) {
+    auto prop = verifyAndCast<VehicleProperty>(propValue.prop);
+    if (!prop.ok()) {
+        return Error() << "Invalid vehicle property: " << prop.error();
+    }
+    if (*prop != vehicleProperty) {
+        return Error() << "Mismatching " << toString(vehicleProperty) << " request, received "
+                       << toString(*prop) << " property";
+    }
+    if (propValue.value.int32Values.size() < minInt32Values) {
+        return Error() << "Int32Values must have at least " << minInt32Values
+                       << " values, received " << propValue.value.int32Values.size();
+    }
+    return {};
+}
+
+Result<void> parseUserInfo(const std::vector<int32_t>& int32Values, size_t startPos,
+                           UserInfo* userInfo) {
+    if (int32Values.size() < startPos + kNumFieldsPerUserInfo) {
+        return Error() << "Int32Values must have at least " << startPos + 2 << " values, received "
+                       << int32Values.size();
+    }
+    userInfo->userId = int32Values[startPos];
+    int32_t intUserFlags = int32Values[startPos + 1];
+    const int32_t combinedFlags = UserInfo::USER_FLAG_SYSTEM | UserInfo::USER_FLAG_GUEST |
+                                  UserInfo::USER_FLAG_EPHEMERAL | UserInfo::USER_FLAG_ADMIN |
+                                  UserInfo::USER_FLAG_DISABLED | UserInfo::USER_FLAG_PROFILE;
+
+    if ((intUserFlags & ~combinedFlags) != 0) {
+        return Error() << "Invalid user flags: " << intUserFlags << ", must be '|' of UserFlags";
+    }
+    userInfo->flags = intUserFlags;
+    return {};
+}
+
+Result<void> parseUsersInfo(const std::vector<int32_t>& int32Values, size_t startPos,
+                            UsersInfo* usersInfo) {
+    if (int32Values.size() < startPos + 3) {
+        return Error() << "Int32Values must have at least " << startPos + 3 << " values, received "
+                       << int32Values.size();
+    }
+    auto ret = parseUserInfo(int32Values, startPos, &usersInfo->currentUser);
+    if (!ret.ok()) {
+        return ret;
+    }
+    usersInfo->numberUsers = int32Values[startPos + 2];
+    usersInfo->existingUsers.resize(usersInfo->numberUsers);
+    for (size_t i = 0; i < static_cast<size_t>(usersInfo->numberUsers); ++i) {
+        ret = parseUserInfo(int32Values, startPos + 3 + (kNumFieldsPerUserInfo * i),
+                            &usersInfo->existingUsers[i]);
+        if (!ret.ok()) {
+            return Error() << "Failed to parse existing user '" << i << "' info: " << ret.error();
+        }
+    }
+    return {};
+}
+
+Result<void> parseUserAssociationTypes(
+        const std::vector<int32_t>& int32Values, size_t startPos, size_t numberAssociationTypes,
+        std::vector<UserIdentificationAssociationType>* associationTypes) {
+    size_t minInt32Values = startPos + numberAssociationTypes;
+    if (int32Values.size() < minInt32Values) {
+        return Error() << "Int32Values must have at least " << minInt32Values
+                       << " values, received " << int32Values.size();
+    }
+    associationTypes->resize(numberAssociationTypes);
+    for (size_t i = 0; i < static_cast<size_t>(numberAssociationTypes); ++i) {
+        size_t pos = startPos + i;
+        auto type = verifyAndCast<UserIdentificationAssociationType>(int32Values[pos]);
+        if (!type.ok()) {
+            return Error() << "Invalid association type in query '" << i << "': " << type.error();
+        }
+        (*associationTypes)[i] = *type;
+    }
+    return {};
+}
+
+Result<void> parseUserAssociations(const std::vector<int32_t>& int32Values, size_t startPos,
+                                   size_t numberAssociations,
+                                   std::vector<UserIdentificationSetAssociation>* associations) {
+    size_t minInt32Values = startPos + (numberAssociations * kNumFieldsPerSetAssociation);
+    if (int32Values.size() < minInt32Values) {
+        return Error() << "Int32Values must have at least " << minInt32Values
+                       << " values, received " << int32Values.size();
+    }
+    associations->resize(numberAssociations);
+    for (size_t i = 0; i < static_cast<size_t>(numberAssociations); ++i) {
+        size_t pos = startPos + (kNumFieldsPerSetAssociation * i);
+        auto type = verifyAndCast<UserIdentificationAssociationType>(int32Values[pos]);
+        if (!type.ok()) {
+            return Error() << "Invalid association type in request '" << i << "': " << type.error();
+        }
+        (*associations)[i].type = *type;
+        auto value = verifyAndCast<UserIdentificationAssociationSetValue>(int32Values[pos + 1]);
+        if (!value.ok()) {
+            return Error() << "Invalid association set value in request '" << i
+                           << "': " << value.error();
+        }
+        (*associations)[i].value = *value;
+    }
+    return {};
+}
+
+}  // namespace
+
+template <typename T>
+Result<T> verifyAndCast(int32_t value) {
+    T castValue = static_cast<T>(value);
+    for (const auto& v : ::ndk::enum_range<T>()) {
+        if (castValue == v) {
+            return castValue;
+        }
+    }
+
+    return Error() << "Value " << value << " not in enum values";
+}
+
+Result<InitialUserInfoRequest> toInitialUserInfoRequest(const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::INITIAL_USER_INFO, /*minInt32Values=*/2);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    InitialUserInfoRequest request;
+    request.requestId = propValue.value.int32Values[0];
+    auto requestType = verifyAndCast<InitialUserInfoRequestType>(propValue.value.int32Values[1]);
+    if (!requestType.ok()) {
+        return Error() << "Invalid InitialUserInfoRequestType: " << requestType.error();
+    }
+    request.requestType = *requestType;
+    ret = parseUsersInfo(propValue.value.int32Values, 2, &request.usersInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse users info: " << ret.error();
+    }
+    return request;
+}
+
+Result<SwitchUserRequest> toSwitchUserRequest(const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::SWITCH_USER, /*minInt32Values=*/2);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    SwitchUserRequest request;
+    auto messageType = verifyAndCast<SwitchUserMessageType>(propValue.value.int32Values[1]);
+    if (!messageType.ok()) {
+        return Error() << "Invalid SwitchUserMessageType: " << messageType.error();
+    }
+    if (*messageType != SwitchUserMessageType::LEGACY_ANDROID_SWITCH &&
+        *messageType != SwitchUserMessageType::ANDROID_SWITCH &&
+        *messageType != SwitchUserMessageType::ANDROID_POST_SWITCH) {
+        return Error() << "Invalid " << toString(*messageType)
+                       << " message type from Android System";
+    }
+    request.requestId = propValue.value.int32Values[0];
+    request.messageType = *messageType;
+    ret = parseUserInfo(propValue.value.int32Values, /*startPos=*/2, &request.targetUser);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse target user info: " << ret.error();
+    }
+    ret = parseUsersInfo(propValue.value.int32Values, /*startPos=*/4, &request.usersInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse users info: " << ret.error();
+    }
+    return request;
+}
+
+Result<CreateUserRequest> toCreateUserRequest(const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::CREATE_USER, /*minInt32Values=*/1);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    CreateUserRequest request;
+    request.requestId = propValue.value.int32Values[0];
+    ret = parseUserInfo(propValue.value.int32Values, /*startPos=*/1, &request.newUserInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse new user info: " << ret.error();
+    }
+    request.newUserName = propValue.value.stringValue;
+    ret = parseUsersInfo(propValue.value.int32Values, /*startPos=*/3, &request.usersInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse users info: " << ret.error();
+    }
+    return request;
+}
+
+Result<RemoveUserRequest> toRemoveUserRequest(const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::REMOVE_USER, /*minInt32Values=*/1);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    RemoveUserRequest request;
+    request.requestId = propValue.value.int32Values[0];
+    ret = parseUserInfo(propValue.value.int32Values, /*startPos=*/1, &request.removedUserInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse removed user info: " << ret.error();
+    }
+    ret = parseUsersInfo(propValue.value.int32Values, /*startPos=*/3, &request.usersInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse users info: " << ret.error();
+    }
+    return request;
+}
+
+Result<UserIdentificationGetRequest> toUserIdentificationGetRequest(
+        const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION,
+                               /*minInt32Values=*/4);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    UserIdentificationGetRequest request;
+    request.requestId = propValue.value.int32Values[0];
+    ret = parseUserInfo(propValue.value.int32Values, /*startPos=*/1, &request.userInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse user info: " << ret.error();
+    }
+    request.numberAssociationTypes = propValue.value.int32Values[3];
+    ret = parseUserAssociationTypes(propValue.value.int32Values, 4, request.numberAssociationTypes,
+                                    &request.associationTypes);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse UserIdentificationAssociationType: " << ret.error();
+    }
+    return request;
+}
+
+Result<UserIdentificationSetRequest> toUserIdentificationSetRequest(
+        const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION,
+                               /*minInt32Values=*/4);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    UserIdentificationSetRequest request;
+    request.requestId = propValue.value.int32Values[0];
+    ret = parseUserInfo(propValue.value.int32Values, /*startPos=*/1, &request.userInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse user info: " << ret.error();
+    }
+    request.numberAssociations = propValue.value.int32Values[3];
+    ret = parseUserAssociations(propValue.value.int32Values, 4, request.numberAssociations,
+                                &request.associations);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse UserIdentificationSetAssociation: " << ret.error();
+    }
+    return request;
+}
+
+Result<VehiclePropValuePool::RecyclableType> toVehiclePropValue(VehiclePropValuePool& pool,
+                                                                const SwitchUserRequest& request) {
+    if (request.messageType != SwitchUserMessageType::VEHICLE_REQUEST) {
+        return Errorf("Invalid %s message type %s from HAL",
+                      toString(VehicleProperty::SWITCH_USER).c_str(),
+                      toString(request.messageType).c_str());
+    }
+    int32_t switchUserProp = toInt(VehicleProperty::SWITCH_USER);
+    auto propValue = pool.obtain(getPropType(switchUserProp));
+    propValue->prop = switchUserProp;
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values.resize(3);
+    propValue->value.int32Values[0] = static_cast<int32_t>(request.requestId);
+    propValue->value.int32Values[1] = static_cast<int32_t>(request.messageType);
+    propValue->value.int32Values[2] = static_cast<int32_t>(request.targetUser.userId);
+    return propValue;
+}
+
+VehiclePropValuePool::RecyclableType toVehiclePropValue(VehiclePropValuePool& pool,
+                                                        const InitialUserInfoResponse& response) {
+    int32_t initialUserInfoProp = toInt(VehicleProperty::INITIAL_USER_INFO);
+    auto propValue = pool.obtain(getPropType(initialUserInfoProp));
+    propValue->prop = initialUserInfoProp;
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values.resize(4);
+    propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+    propValue->value.int32Values[1] = static_cast<int32_t>(response.action);
+    propValue->value.int32Values[2] = static_cast<int32_t>(response.userToSwitchOrCreate.userId);
+    propValue->value.int32Values[3] = response.userToSwitchOrCreate.flags;
+    propValue->value.stringValue = std::string(response.userLocales) + std::string(kSeparator) +
+                                   std::string(response.userNameToCreate);
+    return propValue;
+}
+
+VehiclePropValuePool::RecyclableType toVehiclePropValue(VehiclePropValuePool& pool,
+                                                        const SwitchUserResponse& response) {
+    int32_t switchUserProp = toInt(VehicleProperty::SWITCH_USER);
+    auto propValue = pool.obtain(getPropType(switchUserProp));
+    propValue->prop = switchUserProp;
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values.resize(3);
+    propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+    propValue->value.int32Values[1] = static_cast<int32_t>(response.messageType);
+    propValue->value.int32Values[2] = static_cast<int32_t>(response.status);
+    if (response.status == SwitchUserStatus::FAILURE) {
+        propValue->value.stringValue = response.errorMessage;
+    }
+    return propValue;
+}
+
+VehiclePropValuePool::RecyclableType toVehiclePropValue(VehiclePropValuePool& pool,
+                                                        const CreateUserResponse& response) {
+    int32_t createUserProp = toInt(VehicleProperty::CREATE_USER);
+    auto propValue = pool.obtain(getPropType(createUserProp));
+    propValue->prop = createUserProp;
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values.resize(2);
+    propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+    propValue->value.int32Values[1] = static_cast<int32_t>(response.status);
+    if (response.status == CreateUserStatus::FAILURE) {
+        propValue->value.stringValue = response.errorMessage;
+    }
+    return propValue;
+}
+
+VehiclePropValuePool::RecyclableType toVehiclePropValue(
+        VehiclePropValuePool& pool, const UserIdentificationResponse& response) {
+    int32_t userIdAssocProp = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+    auto propValue = pool.obtain(getPropType(userIdAssocProp));
+    propValue->prop = userIdAssocProp;
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values.resize(2 + (response.numberAssociation * 2));
+    propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+    propValue->value.int32Values[1] = static_cast<int32_t>(response.numberAssociation);
+    for (size_t i = 0; i < static_cast<size_t>(response.numberAssociation); ++i) {
+        size_t int32ValuesPos = 2 + (2 * i);
+        propValue->value.int32Values[int32ValuesPos] =
+                static_cast<int32_t>(response.associations[i].type);
+        propValue->value.int32Values[int32ValuesPos + 1] =
+                static_cast<int32_t>(response.associations[i].value);
+    }
+    if (!response.errorMessage.empty()) {
+        propValue->value.stringValue = response.errorMessage;
+    }
+    return propValue;
+}
+
+}  // namespace user_hal_helper
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/userhal/test/Android.bp
new file mode 100644
index 0000000..7d0a534
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/test/Android.bp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "FakeUserHalTest",
+    vendor: true,
+    srcs: ["*.cpp"],
+    defaults: ["VehicleHalDefaults"],
+    static_libs: [
+        "FakeUserHal",
+        "VehicleHalUtils",
+        "libgtest",
+        "libgmock",
+    ],
+    test_suites: ["device-tests"],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/test/UserHalHelper_test.cpp b/automotive/vehicle/aidl/impl/fake_impl/userhal/test/UserHalHelper_test.cpp
new file mode 100644
index 0000000..2afb2e3
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/test/UserHalHelper_test.cpp
@@ -0,0 +1,715 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "UserHalHelper.h"
+
+#include <VehicleUtils.h>
+#include <aidl/android/hardware/automotive/vehicle/InitialUserInfoResponseAction.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <cstdint>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+namespace user_hal_helper {
+
+namespace {
+
+using ::testing::Eq;
+using ::testing::Gt;
+using ::testing::IsNull;
+using ::testing::NotNull;
+using ::testing::Pointee;
+
+using ::aidl::android::hardware::automotive::vehicle::CreateUserRequest;
+using ::aidl::android::hardware::automotive::vehicle::CreateUserResponse;
+using ::aidl::android::hardware::automotive::vehicle::CreateUserStatus;
+using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoRequest;
+using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoRequestType;
+using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoResponse;
+using ::aidl::android::hardware::automotive::vehicle::InitialUserInfoResponseAction;
+using ::aidl::android::hardware::automotive::vehicle::RemoveUserRequest;
+using ::aidl::android::hardware::automotive::vehicle::SwitchUserMessageType;
+using ::aidl::android::hardware::automotive::vehicle::SwitchUserRequest;
+using ::aidl::android::hardware::automotive::vehicle::SwitchUserResponse;
+using ::aidl::android::hardware::automotive::vehicle::SwitchUserStatus;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationAssociationSetValue;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationAssociationType;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationAssociationValue;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationGetRequest;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationResponse;
+using ::aidl::android::hardware::automotive::vehicle::UserIdentificationSetRequest;
+using ::aidl::android::hardware::automotive::vehicle::UserInfo;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+constexpr int32_t INITIAL_USER_INFO = toInt(VehicleProperty::INITIAL_USER_INFO);
+constexpr int32_t SWITCH_USER = toInt(VehicleProperty::SWITCH_USER);
+constexpr int32_t CREATE_USER = toInt(VehicleProperty::CREATE_USER);
+constexpr int32_t REMOVE_USER = toInt(VehicleProperty::REMOVE_USER);
+constexpr int32_t USER_IDENTIFICATION_ASSOCIATION =
+        toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+
+constexpr int32_t FIRST_BOOT_AFTER_OTA = toInt(InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA);
+constexpr int32_t LEGACY_ANDROID_SWITCH = toInt(SwitchUserMessageType::LEGACY_ANDROID_SWITCH);
+constexpr int32_t VEHICLE_REQUEST = toInt(SwitchUserMessageType::VEHICLE_REQUEST);
+
+constexpr int32_t NONE_USER = 0;
+constexpr int32_t GUEST_USER = toInt(UserInfo::USER_FLAG_GUEST);
+constexpr int32_t SYSTEM_USER = toInt(UserInfo::USER_FLAG_SYSTEM);
+constexpr int32_t SYSTEM_ADMIN_USER = SYSTEM_USER | toInt(UserInfo::USER_FLAG_ADMIN);
+// 0x1111 is not a valid UserFlags combination.
+constexpr int32_t INVALID_USER_FLAG = 0x1111;
+
+constexpr int32_t USER_ID_ASSOC_KEY_FOB = toInt(UserIdentificationAssociationType::KEY_FOB);
+constexpr int32_t USER_ID_ASSOC_CUSTOM_1 = toInt(UserIdentificationAssociationType::CUSTOM_1);
+
+constexpr int32_t USER_ID_ASSOC_SET_CURRENT_USER =
+        toInt(UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER);
+constexpr int32_t USER_ID_ASSOC_UNSET_CURRENT_USER =
+        toInt(UserIdentificationAssociationSetValue::DISASSOCIATE_CURRENT_USER);
+
+constexpr int32_t USER_ID_ASSOC_CURRENT_USER =
+        toInt(UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER);
+constexpr int32_t USER_ID_ASSOC_NO_USER =
+        toInt(UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER);
+
+}  // namespace
+
+TEST(UserHalHelperTest, TestToInitialUserInfoRequest) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
+                                      10, NONE_USER}},
+    };
+    InitialUserInfoRequest expected{
+            .requestId = 23,
+            .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA,
+            .usersInfo = {{10, 0}, 2, {{0, SYSTEM_USER}, {10, 0}}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestUserFlagsBitCombination) {
+    // SYSTEM_ADMIN_USER is two UserFlags combined.
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0,
+                                      SYSTEM_ADMIN_USER, 10, NONE_USER}},
+    };
+    InitialUserInfoRequest expected{
+            .requestId = 23,
+            .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA,
+            .usersInfo = {{10, 0}, 2, {{0, SYSTEM_ADMIN_USER}, {10, 0}}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestUserInvalidUserFlag) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0,
+                                      INVALID_USER_FLAG, 10, NONE_USER}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid user flags";
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INT32_MAX,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
+                                      10, NONE_USER}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithInvalidRequestType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, INT32_MAX, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+                                      NONE_USER}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid request type";
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithInvalidUserFlag) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
+                                      10, INT32_MAX}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid user flags";
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithIncompleteUsersInfo) {
+    VehiclePropValue propValueMissingSecondUserInfo{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0,
+                                      SYSTEM_USER /*Missing 2nd UserInfo*/}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValueMissingSecondUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+    VehiclePropValue propValueMissingUsersInfo{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, /*Missing UsersInfo*/}},
+    };
+
+    actual = toInitialUserInfoRequest(propValueMissingUsersInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+}
+
+TEST(UserHalHelperTest, TestToSwitchUserRequest) {
+    VehiclePropValue propValue{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2,
+                                      0, SYSTEM_USER, 10, NONE_USER}},
+    };
+    SwitchUserRequest expected{
+            .requestId = 23,
+            .messageType = SwitchUserMessageType::LEGACY_ANDROID_SWITCH,
+            .targetUser = {0, SYSTEM_USER},
+            .usersInfo = {{10, 0}, 2, {{0, SYSTEM_USER}, {10, 0}}},
+    };
+
+    auto actual = toSwitchUserRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2,
+                                      0, SYSTEM_USER, 10, NONE_USER}},
+    };
+
+    auto actual = toSwitchUserRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithInvalidMessageType) {
+    VehiclePropValue propValueIncompatibleMessageType{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, VEHICLE_REQUEST, 0, SYSTEM_USER, 10, NONE_USER, 2, 0,
+                                      SYSTEM_USER, 10, NONE_USER}},
+    };
+
+    auto actual = toSwitchUserRequest(propValueIncompatibleMessageType);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on incompatible message type";
+
+    VehiclePropValue propValueInvalidMessageType{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, INT32_MAX, 0, SYSTEM_USER, 10, NONE_USER, 2, 0,
+                                      SYSTEM_USER, 10, NONE_USER}},
+    };
+
+    actual = toSwitchUserRequest(propValueInvalidMessageType);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid message type";
+}
+
+TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithIncompleteUsersInfo) {
+    VehiclePropValue propValueMissingSecondUserInfo{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2,
+                                      0, SYSTEM_USER,
+                                      /*Missing 2nd UserInfo*/}},
+    };
+
+    auto actual = toSwitchUserRequest(propValueMissingSecondUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+    VehiclePropValue propValueMissingUsersInfo{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER,
+                                      /*Missing UsersInfo*/}},
+    };
+
+    actual = toSwitchUserRequest(propValueMissingUsersInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+
+    VehiclePropValue propValueMissingTargetUser{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, /*Missing target UserInfo*/}},
+    };
+
+    actual = toSwitchUserRequest(propValueMissingTargetUser);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing target user info";
+}
+
+TEST(UserHalHelperTest, TestToCreateUserRequest) {
+    VehiclePropValue propValue{
+            .prop = CREATE_USER,
+            .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+                                      NONE_USER},
+                      .stringValue = "Guest11"},
+    };
+    CreateUserRequest expected{
+            .requestId = 23,
+            .newUserInfo = {11, GUEST_USER},
+            .newUserName = "Guest11",
+            .usersInfo = {{10, 0}, 2, {{0, SYSTEM_USER}, {10, 0}}},
+    };
+
+    auto actual = toCreateUserRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToCreateUserRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+                                      NONE_USER},
+                      .stringValue = "Guest11"},
+    };
+
+    auto actual = toCreateUserRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToCreateUserRequestWithIncompleteUsersInfo) {
+    VehiclePropValue propValueMissingSecondUserInfo{
+            .prop = CREATE_USER,
+            .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0,
+                                      SYSTEM_USER /*Missing 2nd UserInfo*/},
+                      .stringValue = "Guest11"},
+    };
+
+    auto actual = toCreateUserRequest(propValueMissingSecondUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+    VehiclePropValue propValueMissingUsersInfo{
+            .prop = CREATE_USER,
+            .value = {.int32Values = {23, 11, GUEST_USER, /*Missing UsersInfo*/},
+                      .stringValue = "Guest11"},
+    };
+
+    actual = toCreateUserRequest(propValueMissingUsersInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+
+    VehiclePropValue propValueMissingCreateUserInfo{
+            .prop = CREATE_USER,
+            .value = {.int32Values = {23, /*Missing create UserInfo*/}, .stringValue = "Guest11"},
+    };
+
+    actual = toCreateUserRequest(propValueMissingCreateUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing create user info";
+}
+
+TEST(UserHalHelperTest, TestToRemoveUserRequest) {
+    VehiclePropValue propValue{
+            .prop = REMOVE_USER,
+            .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+                                      NONE_USER}},
+    };
+    RemoveUserRequest expected{
+            .requestId = 23,
+            .removedUserInfo = {10, 0},
+            .usersInfo = {{10, 0}, 2, {{0, SYSTEM_USER}, {10, 0}}},
+    };
+
+    auto actual = toRemoveUserRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToRemoveUserRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+                                      NONE_USER}},
+    };
+
+    auto actual = toRemoveUserRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToRemoveUserRequestWithIncompleteUsersInfo) {
+    VehiclePropValue propValueMissingSecondUserInfo{
+            .prop = REMOVE_USER,
+            .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0,
+                                      SYSTEM_USER /*Missing 2nd UserInfo*/}},
+    };
+
+    auto actual = toRemoveUserRequest(propValueMissingSecondUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+    VehiclePropValue propValueMissingUsersInfo{
+            .prop = REMOVE_USER,
+            .value = {.int32Values = {23, 10, NONE_USER, /*Missing UsersInfo*/}},
+    };
+
+    actual = toRemoveUserRequest(propValueMissingUsersInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+
+    VehiclePropValue propValueMissingRemoveUserInfo{
+            .prop = REMOVE_USER,
+            .value = {.int32Values = {23, /*Missing remove UserInfo*/}},
+    };
+
+    actual = toRemoveUserRequest(propValueMissingRemoveUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing remove user info";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequest) {
+    VehiclePropValue propValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+                                      USER_ID_ASSOC_CUSTOM_1}},
+    };
+    UserIdentificationGetRequest expected{
+            .requestId = 23,
+            .userInfo = {10, 0},
+            .numberAssociationTypes = 2,
+            .associationTypes = {UserIdentificationAssociationType::KEY_FOB,
+                                 UserIdentificationAssociationType::CUSTOM_1},
+    };
+
+    auto actual = toUserIdentificationGetRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+                                      USER_ID_ASSOC_CUSTOM_1}},
+    };
+
+    auto actual = toUserIdentificationGetRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithInvalidAssociationTypes) {
+    VehiclePropValue propValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 1, INT32_MAX}},
+    };
+
+    auto actual = toUserIdentificationGetRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid association type";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithIncompleteAssociationTypes) {
+    VehiclePropValue propValueMissingSecondAssociationType{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 2,
+                                      USER_ID_ASSOC_KEY_FOB /*Missing 2nd association type*/}},
+    };
+
+    auto actual = toUserIdentificationGetRequest(propValueMissingSecondAssociationType);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second association type";
+
+    VehiclePropValue propValueMissingNumberAssociationTypes{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, /*Missing number association types*/}},
+    };
+
+    actual = toUserIdentificationGetRequest(propValueMissingNumberAssociationTypes);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithMissingUserInfo) {
+    VehiclePropValue propValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, /*Missing user info*/}},
+    };
+
+    auto actual = toUserIdentificationGetRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing UserInfo";
+}
+
+TEST(UserHalHelperTest, TestToUserIdentificationSetRequest) {
+    VehiclePropValue propValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+                                      USER_ID_ASSOC_SET_CURRENT_USER, USER_ID_ASSOC_CUSTOM_1,
+                                      USER_ID_ASSOC_UNSET_CURRENT_USER}},
+    };
+    UserIdentificationSetRequest expected{
+            .requestId = 23,
+            .userInfo = {10, 0},
+            .numberAssociations = 2,
+            .associations = {{UserIdentificationAssociationType::KEY_FOB,
+                              UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER},
+                             {UserIdentificationAssociationType::CUSTOM_1,
+                              UserIdentificationAssociationSetValue::DISASSOCIATE_CURRENT_USER}},
+    };
+
+    auto actual = toUserIdentificationSetRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+                                      USER_ID_ASSOC_SET_CURRENT_USER, USER_ID_ASSOC_CUSTOM_1,
+                                      USER_ID_ASSOC_UNSET_CURRENT_USER}},
+    };
+
+    auto actual = toUserIdentificationSetRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithInvalidAssociations) {
+    VehiclePropValue propValueInvalidAssociationType{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 1, INT32_MAX,
+                                      USER_ID_ASSOC_SET_CURRENT_USER}},
+    };
+
+    auto actual = toUserIdentificationSetRequest(propValueInvalidAssociationType);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid association type";
+
+    VehiclePropValue propValueInvalidAssociationValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, USER_ID_ASSOC_KEY_FOB, INT32_MAX}},
+    };
+
+    actual = toUserIdentificationSetRequest(propValueInvalidAssociationValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithIncompleteAssociations) {
+    VehiclePropValue propValueMissingSecondAssociationType{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+                                      USER_ID_ASSOC_SET_CURRENT_USER,
+                                      /*Missing 2nd association*/}},
+    };
+
+    auto actual = toUserIdentificationSetRequest(propValueMissingSecondAssociationType);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second association type";
+
+    VehiclePropValue propValueMissingNumberAssociationTypes{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, /*Missing number associations*/}},
+    };
+
+    actual = toUserIdentificationSetRequest(propValueMissingNumberAssociationTypes);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithMissingUserInfo) {
+    VehiclePropValue propValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, /*Missing user info*/}},
+    };
+
+    auto actual = toUserIdentificationSetRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing UserInfo";
+}
+
+TEST(UserHalHelperTest, TestSwitchUserRequestToVehiclePropValue) {
+    SwitchUserRequest request{
+            .requestId = 23,
+            .messageType = SwitchUserMessageType::VEHICLE_REQUEST,
+            .targetUser = {11, GUEST_USER},
+    };
+    VehiclePropValue expected{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23,
+                                      static_cast<int32_t>(SwitchUserMessageType::VEHICLE_REQUEST),
+                                      11}},
+    };
+
+    VehiclePropValuePool pool;
+    auto result = toVehiclePropValue(pool, request);
+
+    ASSERT_TRUE(result.ok());
+    EXPECT_THAT(result.value()->timestamp, Gt(0));
+    // Don't rely on real timestamp in tests as the expected and actual objects won't have the same
+    // timestamps. Thus remove the timestamps before comparing them.
+    result.value()->timestamp = 0;
+    EXPECT_THAT(result.value(), Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestFailsSwitchUserRequestToVehiclePropValueWithIncompatibleMessageType) {
+    SwitchUserRequest request{
+            .requestId = 23,
+            .messageType = SwitchUserMessageType::VEHICLE_RESPONSE,
+            .targetUser = {11, GUEST_USER},
+    };
+
+    VehiclePropValuePool pool;
+    auto result = toVehiclePropValue(pool, request);
+
+    EXPECT_FALSE(result.ok());
+}
+
+TEST(UserHalHelperTest, TestInitialUserInfoResponseToVehiclePropValue) {
+    InitialUserInfoResponse response{
+            .requestId = 23,
+            .action = InitialUserInfoResponseAction::CREATE,
+            .userToSwitchOrCreate = {11, GUEST_USER},
+            .userLocales = "en-US,pt-BR",
+            .userNameToCreate = "Owner",
+    };
+    VehiclePropValue expected{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23,
+                                      static_cast<int32_t>(InitialUserInfoResponseAction::CREATE),
+                                      11, GUEST_USER},
+                      .stringValue = "en-US,pt-BR||Owner"},
+    };
+
+    VehiclePropValuePool pool;
+    auto actual = toVehiclePropValue(pool, response);
+
+    ASSERT_THAT(actual, NotNull());
+    EXPECT_THAT(actual->timestamp, Gt(0));
+    actual->timestamp = 0;
+    EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestSwitchUserResponseToVehiclePropValue) {
+    SwitchUserResponse response{
+            .requestId = 23,
+            .messageType = SwitchUserMessageType::VEHICLE_RESPONSE,
+            .status = SwitchUserStatus::FAILURE,
+            .errorMessage = "random error",
+    };
+    VehiclePropValue expected{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23,
+                                      static_cast<int32_t>(SwitchUserMessageType::VEHICLE_RESPONSE),
+                                      static_cast<int32_t>(SwitchUserStatus::FAILURE)},
+                      .stringValue = "random error"},
+    };
+
+    VehiclePropValuePool pool;
+    auto actual = toVehiclePropValue(pool, response);
+
+    ASSERT_THAT(actual, NotNull());
+    EXPECT_THAT(actual->timestamp, Gt(0));
+    actual->timestamp = 0;
+    EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestCreateUserResponseToVehiclePropValue) {
+    CreateUserResponse response{
+            .requestId = 23,
+            .status = CreateUserStatus::FAILURE,
+            .errorMessage = "random error",
+    };
+    VehiclePropValue expected{
+            .prop = CREATE_USER,
+            .value = {.int32Values = {23, static_cast<int32_t>(CreateUserStatus::FAILURE)},
+                      .stringValue = "random error"},
+    };
+
+    VehiclePropValuePool pool;
+    auto actual = toVehiclePropValue(pool, response);
+
+    ASSERT_THAT(actual, NotNull());
+    EXPECT_THAT(actual->timestamp, Gt(0));
+    actual->timestamp = 0;
+    EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestUserIdentificationResponseToVehiclePropValue) {
+    UserIdentificationResponse response{
+            .requestId = 23,
+            .numberAssociation = 2,
+            .associations = {{UserIdentificationAssociationType::KEY_FOB,
+                              UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER},
+                             {UserIdentificationAssociationType::CUSTOM_1,
+                              UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER}},
+            .errorMessage = "random error",
+    };
+    VehiclePropValue expected{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 2, USER_ID_ASSOC_KEY_FOB, USER_ID_ASSOC_CURRENT_USER,
+                                      USER_ID_ASSOC_CUSTOM_1, USER_ID_ASSOC_NO_USER},
+                      .stringValue = "random error"},
+    };
+
+    VehiclePropValuePool pool;
+    auto actual = toVehiclePropValue(pool, response);
+
+    ASSERT_THAT(actual, NotNull());
+    EXPECT_THAT(actual->timestamp, Gt(0));
+    actual->timestamp = 0;
+    EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+}  // namespace user_hal_helper
+}  // namespace fake
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp
new file mode 100644
index 0000000..7670c25
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library {
+    name: "VehicleHalProtoMessageConverter",
+    srcs: [
+        "src/*.cpp",
+    ],
+    vendor: true,
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    shared_libs: ["libprotobuf-cpp-full"],
+    static_libs: [
+        "VehicleHalProtos",
+        "VehicleHalUtils",
+    ],
+    defaults: ["VehicleHalDefaults"],
+    export_static_lib_headers: ["VehicleHalUtils"],
+}
+
+cc_test {
+    name: "VehicleHalProtoMessageConverterTest",
+    srcs: [
+        "test/*.cpp",
+    ],
+    vendor: true,
+    defaults: ["VehicleHalDefaults"],
+    shared_libs: ["libprotobuf-cpp-full"],
+    static_libs: [
+        "VehicleHalProtoMessageConverter",
+        "VehicleHalProtos",
+        "VehicleHalUtils",
+        "libgtest",
+    ],
+    header_libs: ["VehicleHalDefaultConfig"],
+    test_suites: ["device-tests"],
+}
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h
new file mode 100644
index 0000000..1c26fe8
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_grpc_utils_proto_message_converter_include_ProtoMessageConverter_H_
+#define android_hardware_automotive_vehicle_aidl_impl_grpc_utils_proto_message_converter_include_ProtoMessageConverter_H_
+
+#include <VehicleHalTypes.h>
+#include <android/hardware/automotive/vehicle/VehicleAreaConfig.pb.h>
+#include <android/hardware/automotive/vehicle/VehiclePropConfig.pb.h>
+#include <android/hardware/automotive/vehicle/VehiclePropValue.pb.h>
+#include <android/hardware/automotive/vehicle/VehiclePropertyAccess.pb.h>
+#include <android/hardware/automotive/vehicle/VehiclePropertyChangeMode.pb.h>
+#include <android/hardware/automotive/vehicle/VehiclePropertyStatus.pb.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace proto_msg_converter {
+
+// Convert AIDL VehiclePropConfig to Protobuf VehiclePropConfig.
+void aidlToProto(
+        const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig& inAidlConfig,
+        ::android::hardware::automotive::vehicle::proto::VehiclePropConfig* outProtoConfig);
+// Convert Protobuf VehiclePropConfig to AIDL VehiclePropConfig.
+void protoToAidl(
+        const ::android::hardware::automotive::vehicle::proto::VehiclePropConfig& inProtoConfig,
+        ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig* outAidlConfig);
+// Convert AIDL VehiclePropValue to Protobuf VehiclePropValue.
+void aidlToProto(const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& inAidlVal,
+                 ::android::hardware::automotive::vehicle::proto::VehiclePropValue* outProtoVal);
+// Convert Protobuf VehiclePropValue to AIDL VehiclePropValue.
+void protoToAidl(
+        const ::android::hardware::automotive::vehicle::proto::VehiclePropValue& inProtoVal,
+        ::aidl::android::hardware::automotive::vehicle::VehiclePropValue* outAidlVal);
+
+}  // namespace proto_msg_converter
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_grpc_utils_proto_message_converter_include_ProtoMessageConverter_H_
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp
new file mode 100644
index 0000000..6cbc7e5
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ProtoMsgConverter"
+
+#include "ProtoMessageConverter.h"
+
+#include <VehicleUtils.h>
+
+#include <memory>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace proto_msg_converter {
+
+namespace aidl_vehicle = ::aidl::android::hardware::automotive::vehicle;
+namespace proto = ::android::hardware::automotive::vehicle::proto;
+
+// Copy the vector PROTO_VECNAME of protobuf class PROTO_VALUE to
+// VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME, every element of PROTO_VECNAME is casted by CAST.
+#define CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, \
+                                            VHAL_TYPE_VECNAME, CAST)                     \
+    do {                                                                                 \
+        (VHAL_TYPE_VALUE)->VHAL_TYPE_VECNAME.resize(PROTO_VALUE.PROTO_VECNAME##_size()); \
+        size_t idx = 0;                                                                  \
+        for (auto& value : PROTO_VALUE.PROTO_VECNAME()) {                                \
+            VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME[idx++] = CAST(value);                     \
+        }                                                                                \
+    } while (0)
+
+// Copying the vector PROTO_VECNAME of protobuf class PROTO_VALUE to
+// VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME.
+#define COPY_PROTOBUF_VEC_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, \
+                                       VHAL_TYPE_VECNAME)                           \
+    CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE(                                            \
+            PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, VHAL_TYPE_VECNAME, /*NO CAST*/)
+
+void aidlToProto(const aidl_vehicle::VehiclePropConfig& in, proto::VehiclePropConfig* out) {
+    out->set_prop(in.prop);
+    out->set_access(static_cast<proto::VehiclePropertyAccess>(toInt(in.access)));
+    out->set_change_mode(static_cast<proto::VehiclePropertyChangeMode>(toInt(in.changeMode)));
+    out->set_config_string(in.configString.c_str(), in.configString.size());
+    out->set_min_sample_rate(in.minSampleRate);
+    out->set_max_sample_rate(in.maxSampleRate);
+
+    for (auto& configElement : in.configArray) {
+        out->add_config_array(configElement);
+    }
+
+    out->clear_area_configs();
+    for (auto& areaConfig : in.areaConfigs) {
+        auto* protoACfg = out->add_area_configs();
+        protoACfg->set_area_id(areaConfig.areaId);
+        protoACfg->set_min_int64_value(areaConfig.minInt64Value);
+        protoACfg->set_max_int64_value(areaConfig.maxInt64Value);
+        protoACfg->set_min_float_value(areaConfig.minFloatValue);
+        protoACfg->set_max_float_value(areaConfig.maxFloatValue);
+        protoACfg->set_min_int32_value(areaConfig.minInt32Value);
+        protoACfg->set_max_int32_value(areaConfig.maxInt32Value);
+    }
+}
+
+void protoToAidl(const proto::VehiclePropConfig& in, aidl_vehicle::VehiclePropConfig* out) {
+    out->prop = in.prop();
+    out->access = static_cast<aidl_vehicle::VehiclePropertyAccess>(in.access());
+    out->changeMode = static_cast<aidl_vehicle::VehiclePropertyChangeMode>(in.change_mode());
+    out->configString = in.config_string();
+    out->minSampleRate = in.min_sample_rate();
+    out->maxSampleRate = in.max_sample_rate();
+
+    COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, config_array, out, configArray);
+
+    auto cast_to_acfg = [](const proto::VehicleAreaConfig& protoAcfg) {
+        return aidl_vehicle::VehicleAreaConfig{
+                .areaId = protoAcfg.area_id(),
+                .minInt32Value = protoAcfg.min_int32_value(),
+                .maxInt32Value = protoAcfg.max_int32_value(),
+                .minInt64Value = protoAcfg.min_int64_value(),
+                .maxInt64Value = protoAcfg.max_int64_value(),
+                .minFloatValue = protoAcfg.min_float_value(),
+                .maxFloatValue = protoAcfg.max_float_value(),
+        };
+    };
+    CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, area_configs, out, areaConfigs, cast_to_acfg);
+}
+
+void aidlToProto(const aidl_vehicle::VehiclePropValue& in, proto::VehiclePropValue* out) {
+    out->set_prop(in.prop);
+    out->set_timestamp(in.timestamp);
+    out->set_status(static_cast<proto::VehiclePropertyStatus>(in.status));
+    out->set_area_id(in.areaId);
+    out->set_string_value(in.value.stringValue);
+    out->set_byte_values(in.value.byteValues.data(), in.value.byteValues.size());
+
+    for (auto& int32Value : in.value.int32Values) {
+        out->add_int32_values(int32Value);
+    }
+
+    for (auto& int64Value : in.value.int64Values) {
+        out->add_int64_values(int64Value);
+    }
+
+    for (auto& floatValue : in.value.floatValues) {
+        out->add_float_values(floatValue);
+    }
+}
+
+void protoToAidl(const proto::VehiclePropValue& in, aidl_vehicle::VehiclePropValue* out) {
+    out->prop = in.prop();
+    out->timestamp = in.timestamp();
+    out->status = static_cast<aidl_vehicle::VehiclePropertyStatus>(in.status());
+    out->areaId = in.area_id();
+    out->value.stringValue = in.string_value();
+    for (const char& byte : in.byte_values()) {
+        out->value.byteValues.push_back(byte);
+    }
+
+    COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, int32_values, out, value.int32Values);
+    COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, int64_values, out, value.int64Values);
+    COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, float_values, out, value.floatValues);
+}
+
+#undef COPY_PROTOBUF_VEC_TO_VHAL_TYPE
+#undef CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE
+
+}  // namespace proto_msg_converter
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
new file mode 100644
index 0000000..c742db5
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <vector>
+
+#include <DefaultConfig.h>
+#include <ProtoMessageConverter.h>
+#include <VehicleHalTypes.h>
+#include <android-base/format.h>
+#include <android/hardware/automotive/vehicle/VehiclePropConfig.pb.h>
+#include <android/hardware/automotive/vehicle/VehiclePropValue.pb.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace proto_msg_converter {
+
+namespace {
+
+namespace proto = ::android::hardware::automotive::vehicle::proto;
+namespace aidl_vehicle = ::aidl::android::hardware::automotive::vehicle;
+
+std::vector<aidl_vehicle::VehiclePropConfig> prepareTestConfigs() {
+    std::vector<aidl_vehicle::VehiclePropConfig> configs;
+    for (auto& property : defaultconfig::getDefaultConfigs()) {
+        configs.push_back(property.config);
+    }
+    return configs;
+}
+
+std::vector<aidl_vehicle::VehiclePropValue> prepareTestValues() {
+    std::vector<aidl_vehicle::VehiclePropValue> values;
+    int64_t timestamp = 1;
+    for (auto& property : defaultconfig::getDefaultConfigs()) {
+        values.push_back({
+                .timestamp = timestamp,
+                .areaId = 123,
+                .prop = property.config.prop,
+                .value = property.initialValue,
+                .status = aidl_vehicle::VehiclePropertyStatus::ERROR,
+        });
+    }
+    return values;
+}
+
+class PropConfigConversionTest : public testing::TestWithParam<aidl_vehicle::VehiclePropConfig> {};
+
+class PropValueConversionTest : public testing::TestWithParam<aidl_vehicle::VehiclePropValue> {};
+
+}  // namespace
+
+TEST_P(PropConfigConversionTest, testConversion) {
+    proto::VehiclePropConfig protoCfg;
+    aidl_vehicle::VehiclePropConfig aidlCfg;
+
+    aidlToProto(GetParam(), &protoCfg);
+    protoToAidl(protoCfg, &aidlCfg);
+
+    EXPECT_EQ(aidlCfg, GetParam());
+}
+
+TEST_P(PropValueConversionTest, testConversion) {
+    proto::VehiclePropValue protoVal;
+    aidl_vehicle::VehiclePropValue aidlVal;
+
+    aidlToProto(GetParam(), &protoVal);
+    protoToAidl(protoVal, &aidlVal);
+
+    EXPECT_EQ(aidlVal, GetParam());
+}
+
+INSTANTIATE_TEST_SUITE_P(DefaultConfigs, PropConfigConversionTest,
+                         ::testing::ValuesIn(prepareTestConfigs()),
+                         [](const ::testing::TestParamInfo<aidl_vehicle::VehiclePropConfig>& info) {
+                             return ::fmt::format("property_{:d}", info.param.prop);
+                         });
+
+INSTANTIATE_TEST_SUITE_P(TestValues, PropValueConversionTest,
+                         ::testing::ValuesIn(prepareTestValues()),
+                         [](const ::testing::TestParamInfo<aidl_vehicle::VehiclePropValue>& info) {
+                             return ::fmt::format("property_{:d}", info.param.prop);
+                         });
+
+}  // namespace proto_msg_converter
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/hardware/Android.bp b/automotive/vehicle/aidl/impl/hardware/Android.bp
new file mode 100644
index 0000000..edb0f29
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/hardware/Android.bp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library_headers {
+    name: "IVehicleHardware",
+    vendor: true,
+    export_include_dirs: [
+        "include",
+    ],
+    header_libs: [
+        "VehicleHalUtilHeaders",
+    ],
+    export_header_lib_headers: [
+        "VehicleHalUtilHeaders",
+    ],
+}
diff --git a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
new file mode 100644
index 0000000..4b9de2d
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_hardware_include_IVehicleHardware_H_
+#define android_hardware_automotive_vehicle_aidl_impl_hardware_include_IVehicleHardware_H_
+
+#include <VehicleHalTypes.h>
+
+#include <memory>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// A structure used to return dumped information.
+struct DumpResult {
+    // If callerShouldDumpState is true, caller would print the information in buffer and
+    // continue to dump its state, otherwise would just dump the buffer and skip its own
+    // dumping logic.
+    bool callerShouldDumpState;
+    // The dumped information for the caller to print.
+    std::string buffer;
+};
+
+// A structure to represent a set value error event reported from vehicle.
+struct SetValueErrorEvent {
+    ::aidl::android::hardware::automotive::vehicle::StatusCode errorCode;
+    int32_t propId;
+    int32_t areaId;
+};
+
+// An abstract interface to access vehicle hardware.
+// For virtualized VHAL, GrpcVehicleHardware would communicate with a VehicleHardware
+// implementation in another VM through GRPC. For non-virtualzied VHAL, VHAL directly communicates
+// with a VehicleHardware through this interface.
+class IVehicleHardware {
+  public:
+    using SetValuesCallback = std::function<void(
+            std::vector<::aidl::android::hardware::automotive::vehicle::SetValueResult>)>;
+    using GetValuesCallback = std::function<void(
+            std::vector<::aidl::android::hardware::automotive::vehicle::GetValueResult>)>;
+    using PropertyChangeCallback = std::function<void(
+            std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>)>;
+    using PropertySetErrorCallback = std::function<void(std::vector<SetValueErrorEvent>)>;
+
+    virtual ~IVehicleHardware() = default;
+
+    // Get all the property configs.
+    virtual std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+    getAllPropertyConfigs() const = 0;
+
+    // Set property values asynchronously. Server could return before the property set requests
+    // are sent to vehicle bus or before property set confirmation is received. The callback is
+    // safe to be called after the function returns and is safe to be called in a different thread.
+    virtual ::aidl::android::hardware::automotive::vehicle::StatusCode setValues(
+            std::shared_ptr<const SetValuesCallback> callback,
+            const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest>&
+                    requests) = 0;
+
+    // Get property values asynchronously. Server could return before the property values are ready.
+    // The callback is safe to be called after the function returns and is safe to be called in a
+    // different thread.
+    virtual ::aidl::android::hardware::automotive::vehicle::StatusCode getValues(
+            std::shared_ptr<const GetValuesCallback> callback,
+            const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest>&
+                    requests) const = 0;
+
+    // Dump debug information in the server.
+    virtual DumpResult dump(const std::vector<std::string>& options) = 0;
+
+    // Check whether the system is healthy, return {@code StatusCode::OK} for healthy.
+    virtual ::aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() = 0;
+
+    // Register a callback that would be called when there is a property change event from vehicle.
+    virtual void registerOnPropertyChangeEvent(
+            std::unique_ptr<const PropertyChangeCallback> callback) = 0;
+
+    // Register a callback that would be called when there is a property set error event from
+    // vehicle.
+    virtual void registerOnPropertySetErrorEvent(
+            std::unique_ptr<const PropertySetErrorCallback> callback) = 0;
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_hardware_include_IVehicleHardware_H_
diff --git a/automotive/vehicle/aidl/impl/proto/Android.bp b/automotive/vehicle/aidl/impl/proto/Android.bp
new file mode 100644
index 0000000..709307d
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/Android.bp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    // 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"],
+}
+
+filegroup {
+    name: "VehicleHalProtoFiles",
+    srcs: ["**/*.proto"],
+    visibility: ["//hardware/interfaces/automotive/vehicle:__subpackages__"],
+}
+
+genrule {
+    name: "VehicleProtoStub_h",
+    tools: [
+        "aprotoc",
+        "protoc-gen-grpc-cpp-plugin",
+    ],
+    cmd: "$(location aprotoc) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
+    srcs: [
+        ":VehicleHalProtoFiles",
+    ],
+    out: [
+        "android/hardware/automotive/vehicle/DumpResult.pb.h",
+        "android/hardware/automotive/vehicle/StatusCode.pb.h",
+        "android/hardware/automotive/vehicle/VehicleAreaConfig.pb.h",
+        "android/hardware/automotive/vehicle/VehiclePropConfig.pb.h",
+        "android/hardware/automotive/vehicle/VehiclePropertyAccess.pb.h",
+        "android/hardware/automotive/vehicle/VehiclePropertyChangeMode.pb.h",
+        "android/hardware/automotive/vehicle/VehiclePropertyStatus.pb.h",
+        "android/hardware/automotive/vehicle/VehiclePropValue.pb.h",
+        "android/hardware/automotive/vehicle/VehiclePropValueRequest.pb.h",
+    ],
+}
+
+genrule {
+    name: "VehicleProtoStub_cc",
+    tools: [
+        "aprotoc",
+        "protoc-gen-grpc-cpp-plugin",
+    ],
+    cmd: "$(location aprotoc) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
+    srcs: [
+        ":VehicleHalProtoFiles",
+    ],
+    out: [
+        "android/hardware/automotive/vehicle/DumpResult.pb.cc",
+        "android/hardware/automotive/vehicle/StatusCode.pb.cc",
+        "android/hardware/automotive/vehicle/VehicleAreaConfig.pb.cc",
+        "android/hardware/automotive/vehicle/VehiclePropConfig.pb.cc",
+        "android/hardware/automotive/vehicle/VehiclePropertyAccess.pb.cc",
+        "android/hardware/automotive/vehicle/VehiclePropertyChangeMode.pb.cc",
+        "android/hardware/automotive/vehicle/VehiclePropertyStatus.pb.cc",
+        "android/hardware/automotive/vehicle/VehiclePropValue.pb.cc",
+        "android/hardware/automotive/vehicle/VehiclePropValueRequest.pb.cc",
+    ],
+}
+
+cc_library_static {
+    name: "VehicleHalProtos",
+    vendor: true,
+    host_supported: true,
+    include_dirs: [
+        "external/protobuf/src",
+    ],
+    generated_headers: [
+        "VehicleProtoStub_h",
+    ],
+    export_generated_headers: [
+        "VehicleProtoStub_h",
+    ],
+    generated_sources: [
+        "VehicleProtoStub_cc",
+    ],
+    shared_libs: [
+        "libgrpc++_unsecure",
+    ],
+    cflags: [
+        "-Wno-unused-parameter",
+    ],
+}
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpResult.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpResult.proto
new file mode 100644
index 0000000..25bb7d4
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpResult.proto
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+message DumpResult {
+    /* If callerShouldDumpState is true, caller would print the information in buffer and
+     * continue to dump its state, otherwise would just dump the buffer and skip its own
+     * dumping logic. */
+    bool caller_should_dump_state = 1;
+    /* The dumped information for the caller to print. */
+    string buffer = 2;
+}
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto
new file mode 100644
index 0000000..97cb0f8
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto
@@ -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.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+/* Must be in sync with StatusCode.aidl. */
+enum StatusCode {
+    OK = 0;
+
+    /* Try again. */
+    TRY_AGAIN = 1;
+
+    /* Invalid argument provided. */
+    INVALID_ARG = 2;
+
+    /* This code must be returned when device that associated with the vehicle
+     * property is not available. For example, when client tries to set HVAC
+     * temperature when the whole HVAC unit is turned OFF. */
+    NOT_AVAILABLE = 3;
+
+    /* Access denied */
+    ACCESS_DENIED = 4;
+
+    /* Something unexpected has happened in Vehicle HAL */
+    INTERNAL_ERROR = 5;
+};
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto
new file mode 100644
index 0000000..b5b7e80
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+/* Must be in sync with VehicleAreaConfig.aidl. */
+message VehicleAreaConfig {
+    /* Area id is ignored for VehiclePropertyGroup:GLOBAL properties. */
+    int32 area_id = 1;
+
+    /* If the property has @data_enum, leave the range to zero.
+     *
+     * Range will be ignored in the following cases:
+     *    - The VehiclePropertyType is not INT32, INT64 or FLOAT.
+     *    - Both of min value and max value are zero. */
+    int32 min_int32_value = 2;
+    int32 max_int32_value = 3;
+
+    int64 min_int64_value = 4;
+    int64 max_int64_value = 5;
+
+    float min_float_value = 6;
+    float max_float_value = 7;
+};
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto
new file mode 100644
index 0000000..e230d15
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropConfig.proto
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+import "android/hardware/automotive/vehicle/VehicleAreaConfig.proto";
+import "android/hardware/automotive/vehicle/VehiclePropertyAccess.proto";
+import "android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto";
+
+/* Must be in sync with VehiclePropConfig.aidl. */
+message VehiclePropConfig {
+    /* Property identifier */
+    int32 prop = 1;
+
+    /* Defines if the property is read or write or both. */
+    VehiclePropertyAccess access = 2;
+
+    /* Defines the change mode of the property. */
+    VehiclePropertyChangeMode change_mode = 3;
+
+    /* Contains per-area configuration. */
+    repeated VehicleAreaConfig area_configs = 4;
+
+    /* Contains additional configuration parameters */
+    repeated int32 config_array = 5;
+
+    /* Some properties may require additional information passed over this
+     * string. Most properties do not need to set this. */
+    bytes config_string = 6;
+
+    /* Min sample rate in Hz.
+     * Must be defined for VehiclePropertyChangeMode::CONTINUOUS */
+    float min_sample_rate = 7;
+
+    /* Must be defined for VehiclePropertyChangeMode::CONTINUOUS
+     * Max sample rate in Hz. */
+    float max_sample_rate = 8;
+};
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto
new file mode 100644
index 0000000..80c73cb
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+import "android/hardware/automotive/vehicle/VehiclePropertyStatus.proto";
+
+/* Must be in sync with VehiclePropValue.aidl. */
+message VehiclePropValue {
+    /* Time is elapsed nanoseconds since boot */
+    int64 timestamp = 1;
+
+    /* Area type(s) for non-global property it must be one of the value from
+     * VehicleArea* enums or 0 for global properties. */
+    int32 area_id = 2;
+
+    /* Property identifier */
+    int32 prop = 3;
+
+    /* Status of the property */
+    VehiclePropertyStatus status = 4;
+
+    /* This is used for properties of types VehiclePropertyType#INT
+     * and VehiclePropertyType#INT_VEC */
+    repeated int32 int32_values = 5;
+
+    /* This is used for properties of types VehiclePropertyType#FLOAT
+     * and VehiclePropertyType#FLOAT_VEC */
+    repeated float float_values = 6;
+
+    /* This is used for properties of type VehiclePropertyType#INT64 */
+    repeated int64 int64_values = 7;
+
+    /* This is used for properties of type VehiclePropertyType#BYTES */
+    bytes byte_values = 8;
+
+    /* This is used for properties of type VehiclePropertyType#STRING */
+    string string_value = 9;
+};
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto
new file mode 100644
index 0000000..b16daa8
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto
@@ -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.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+import "android/hardware/automotive/vehicle/VehiclePropValue.proto";
+
+message VehiclePropValueRequest {
+    int32 request_id = 1;
+    VehiclePropValue value = 2;
+};
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto
new file mode 100644
index 0000000..55840f0
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyAccess.proto
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+/* Must be in sync with VehiclePropertyAccess.aidl. */
+enum VehiclePropertyAccess {
+    NONE = 0;
+    READ = 1;
+    WRITE = 2;
+    READ_WRITE = 3;
+};
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto
new file mode 100644
index 0000000..c681e3b
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.proto
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+/* Must be in sync with VehiclePropertyChangeMode.aidl. */
+enum VehiclePropertyChangeMode {
+    /* Property of this type must never be changed. Subscription is not supported
+     * for these properties. */
+    STATIC = 0;
+
+    /* Properties of this type must report when there is a change.
+     * IVehicle#get call must return the current value.
+     * Set operation for this property is assumed to be asynchronous. When the
+     * property is read (using IVehicle#get) after IVehicle#set, it may still
+     * return old value until underlying H/W backing this property has actually
+     * changed the state. Once state is changed, the property must dispatch
+     * changed value as event. */
+    ON_CHANGE = 1;
+
+    /* Properties of this type change continuously and require a fixed rate of
+     * sampling to retrieve the data.  Implementers may choose to send extra
+     * notifications on significant value changes. */
+    CONTINUOUS = 2;
+};
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto
new file mode 100644
index 0000000..a44c8f0
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropertyStatus.proto
@@ -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.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+/* Must be in sync with VehiclePropertyStatus.aidl. */
+enum VehiclePropertyStatus {
+    /* Property is available and behaving normally */
+    AVAILABLE = 0;
+    /* A property in this state is not available for reading and writing.  This
+     * is a transient state that depends on the availability of the underlying
+     * implementation (e.g. hardware or driver). It MUST NOT be used to
+     * represent features that this vehicle is always incapable of.  A get() of
+     * a property in this state MAY return an undefined value, but MUST
+     * correctly describe its status as UNAVAILABLE A set() of a property in
+     * this state MAY return NOT_AVAILABLE. The HAL implementation MUST ignore
+     * the value of the status field when writing a property value coming from
+     * Android. */
+    UNAVAILABLE = 1;
+    /* There is an error with this property. */
+    ERROR = 2;
+};
diff --git a/automotive/vehicle/aidl/impl/utils/common/Android.bp b/automotive/vehicle/aidl/impl/utils/common/Android.bp
new file mode 100644
index 0000000..ace505d
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/Android.bp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library {
+    name: "VehicleHalUtils",
+    srcs: ["src/*.cpp"],
+    vendor: true,
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    defaults: ["VehicleHalDefaults"],
+}
+
+cc_library_headers {
+    name: "VehicleHalUtilHeaders",
+    export_include_dirs: ["include"],
+    vendor: true,
+}
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h b/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
new file mode 100644
index 0000000..9a8f19b
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
@@ -0,0 +1,99 @@
+/*
+ * 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 android_hardware_automotive_vehicle_aidl_impl_utils_common_include_ConcurrentQueue_H_
+#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_ConcurrentQueue_H_
+
+#include <android-base/thread_annotations.h>
+
+#include <atomic>
+#include <condition_variable>
+#include <iostream>
+#include <queue>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+template <typename T>
+class ConcurrentQueue {
+  public:
+    void waitForItems() {
+        std::unique_lock<std::mutex> lockGuard(mLock);
+        ::android::base::ScopedLockAssertion lockAssertion(mLock);
+        while (mQueue.empty() && mIsActive) {
+            mCond.wait(lockGuard);
+        }
+    }
+
+    std::vector<T> flush() {
+        std::vector<T> items;
+
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+        if (mQueue.empty()) {
+            return items;
+        }
+        while (!mQueue.empty()) {
+            // Even if the queue is deactivated, we should still flush all the remaining values
+            // in the queue.
+            items.push_back(std::move(mQueue.front()));
+            mQueue.pop();
+        }
+        return items;
+    }
+
+    void push(T&& item) {
+        {
+            std::scoped_lock<std::mutex> lockGuard(mLock);
+            if (!mIsActive) {
+                return;
+            }
+            mQueue.push(std::move(item));
+        }
+        mCond.notify_one();
+    }
+
+    // Deactivates the queue, thus no one can push items to it, also notifies all waiting thread.
+    // The items already in the queue could still be flushed even after the queue is deactivated.
+    void deactivate() {
+        {
+            std::scoped_lock<std::mutex> lockGuard(mLock);
+            mIsActive = false;
+        }
+        // To unblock all waiting consumers.
+        mCond.notify_all();
+    }
+
+    ConcurrentQueue() = default;
+
+    ConcurrentQueue(const ConcurrentQueue&) = delete;
+    ConcurrentQueue& operator=(const ConcurrentQueue&) = delete;
+
+  private:
+    mutable std::mutex mLock;
+    bool mIsActive GUARDED_BY(mLock) = true;
+    std::condition_variable mCond;
+    std::queue<T> mQueue GUARDED_BY(mLock);
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_ConcurrentQueue_H_
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
new file mode 100644
index 0000000..2743578
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_utils_common_include_PropertyUtils_H_
+#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_PropertyUtils_H_
+
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace propertyutils_impl {
+
+// These names are not part of the API since we only expose ints.
+using ::aidl::android::hardware::automotive::vehicle::PortLocationType;
+using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaDoor;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaSeat;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWheel;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
+using ::aidl::android::hardware::automotive::vehicle::VehicleHvacFanDirection;
+using ::aidl::android::hardware::automotive::vehicle::VehicleLightState;
+using ::aidl::android::hardware::automotive::vehicle::VehicleLightSwitch;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+
+}  // namespace propertyutils_impl
+
+// Some handy constants to avoid conversions from enum to int.
+constexpr int ABS_ACTIVE = toInt(propertyutils_impl::VehicleProperty::ABS_ACTIVE);
+constexpr int AP_POWER_STATE_REQ = toInt(propertyutils_impl::VehicleProperty::AP_POWER_STATE_REQ);
+constexpr int AP_POWER_STATE_REPORT =
+        toInt(propertyutils_impl::VehicleProperty::AP_POWER_STATE_REPORT);
+constexpr int DOOR_1_LEFT = toInt(propertyutils_impl::VehicleAreaDoor::ROW_1_LEFT);
+constexpr int DOOR_1_RIGHT = toInt(propertyutils_impl::VehicleAreaDoor::ROW_1_RIGHT);
+constexpr int DOOR_2_LEFT = toInt(propertyutils_impl::VehicleAreaDoor::ROW_2_LEFT);
+constexpr int DOOR_2_RIGHT = toInt(propertyutils_impl::VehicleAreaDoor::ROW_2_RIGHT);
+constexpr int DOOR_REAR = toInt(propertyutils_impl::VehicleAreaDoor::REAR);
+constexpr int WINDOW_1_LEFT = toInt(propertyutils_impl::VehicleAreaWindow::ROW_1_LEFT);
+constexpr int WINDOW_1_RIGHT = toInt(propertyutils_impl::VehicleAreaWindow::ROW_1_RIGHT);
+constexpr int WINDOW_2_LEFT = toInt(propertyutils_impl::VehicleAreaWindow::ROW_2_LEFT);
+constexpr int WINDOW_2_RIGHT = toInt(propertyutils_impl::VehicleAreaWindow::ROW_2_RIGHT);
+constexpr int WINDOW_ROOF_TOP_1 = toInt(propertyutils_impl::VehicleAreaWindow::ROOF_TOP_1);
+constexpr int FAN_DIRECTION_FACE = toInt(propertyutils_impl::VehicleHvacFanDirection::FACE);
+constexpr int FAN_DIRECTION_FLOOR = toInt(propertyutils_impl::VehicleHvacFanDirection::FLOOR);
+constexpr int FAN_DIRECTION_DEFROST = toInt(propertyutils_impl::VehicleHvacFanDirection::DEFROST);
+constexpr int OBD2_LIVE_FRAME = toInt(propertyutils_impl::VehicleProperty::OBD2_LIVE_FRAME);
+constexpr int OBD2_FREEZE_FRAME = toInt(propertyutils_impl::VehicleProperty::OBD2_FREEZE_FRAME);
+constexpr int OBD2_FREEZE_FRAME_INFO =
+        toInt(propertyutils_impl::VehicleProperty::OBD2_FREEZE_FRAME_INFO);
+constexpr int OBD2_FREEZE_FRAME_CLEAR =
+        toInt(propertyutils_impl::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR);
+constexpr int TRACTION_CONTROL_ACTIVE =
+        toInt(propertyutils_impl::VehicleProperty::TRACTION_CONTROL_ACTIVE);
+constexpr int VEHICLE_MAP_SERVICE = toInt(propertyutils_impl::VehicleProperty::VEHICLE_MAP_SERVICE);
+constexpr int WHEEL_TICK = toInt(propertyutils_impl::VehicleProperty::WHEEL_TICK);
+constexpr int SEAT_1_LEFT = toInt(propertyutils_impl::VehicleAreaSeat::ROW_1_LEFT);
+constexpr int SEAT_1_RIGHT = toInt(propertyutils_impl::VehicleAreaSeat::ROW_1_RIGHT);
+constexpr int SEAT_2_LEFT = toInt(propertyutils_impl::VehicleAreaSeat::ROW_2_LEFT);
+constexpr int SEAT_2_RIGHT = toInt(propertyutils_impl::VehicleAreaSeat::ROW_2_RIGHT);
+constexpr int SEAT_2_CENTER = toInt(propertyutils_impl::VehicleAreaSeat::ROW_2_CENTER);
+constexpr int VENDOR_EXTENSION_BOOLEAN_PROPERTY =
+        0x101 | toInt(propertyutils_impl::VehiclePropertyGroup::VENDOR) |
+        toInt(propertyutils_impl::VehiclePropertyType::BOOLEAN) |
+        toInt(propertyutils_impl::VehicleArea::DOOR);
+constexpr int VENDOR_EXTENSION_FLOAT_PROPERTY =
+        0x102 | toInt(propertyutils_impl::VehiclePropertyGroup::VENDOR) |
+        toInt(propertyutils_impl::VehiclePropertyType::FLOAT) |
+        toInt(propertyutils_impl::VehicleArea::SEAT);
+constexpr int VENDOR_EXTENSION_INT_PROPERTY =
+        0x103 | toInt(propertyutils_impl::VehiclePropertyGroup::VENDOR) |
+        toInt(propertyutils_impl::VehiclePropertyType::INT32) |
+        toInt(propertyutils_impl::VehicleArea::WINDOW);
+constexpr int VENDOR_EXTENSION_STRING_PROPERTY =
+        0x104 | toInt(propertyutils_impl::VehiclePropertyGroup::VENDOR) |
+        toInt(propertyutils_impl::VehiclePropertyType::STRING) |
+        toInt(propertyutils_impl::VehicleArea::GLOBAL);
+constexpr int FUEL_DOOR_REAR_LEFT = toInt(propertyutils_impl::PortLocationType::REAR_LEFT);
+constexpr int CHARGE_PORT_FRONT_LEFT = toInt(propertyutils_impl::PortLocationType::FRONT_LEFT);
+constexpr int CHARGE_PORT_REAR_LEFT = toInt(propertyutils_impl::PortLocationType::REAR_LEFT);
+constexpr int LIGHT_STATE_ON = toInt(propertyutils_impl::VehicleLightState::ON);
+constexpr int LIGHT_SWITCH_AUTO = toInt(propertyutils_impl::VehicleLightSwitch::AUTOMATIC);
+constexpr int WHEEL_FRONT_LEFT = toInt(propertyutils_impl::VehicleAreaWheel::LEFT_FRONT);
+constexpr int WHEEL_FRONT_RIGHT = toInt(propertyutils_impl::VehicleAreaWheel::RIGHT_FRONT);
+constexpr int WHEEL_REAR_LEFT = toInt(propertyutils_impl::VehicleAreaWheel::LEFT_REAR);
+constexpr int WHEEL_REAR_RIGHT = toInt(propertyutils_impl::VehicleAreaWheel::RIGHT_REAR);
+constexpr int ALL_WHEELS =
+        WHEEL_FRONT_LEFT | WHEEL_FRONT_RIGHT | WHEEL_REAR_LEFT | WHEEL_REAR_RIGHT;
+constexpr int HVAC_LEFT = SEAT_1_LEFT | SEAT_2_LEFT | SEAT_2_CENTER;
+constexpr int HVAC_RIGHT = SEAT_1_RIGHT | SEAT_2_RIGHT;
+constexpr int HVAC_ALL = HVAC_LEFT | HVAC_RIGHT;
+
+const int32_t HVAC_POWER_PROPERTIES[] = {
+        toInt(propertyutils_impl::VehicleProperty::HVAC_FAN_SPEED),
+        toInt(propertyutils_impl::VehicleProperty::HVAC_FAN_DIRECTION),
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_PropertyUtils_H_
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
new file mode 100644
index 0000000..013d177
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
@@ -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.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleHalTypes_H_
+#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleHalTypes_H_
+
+#include <aidl/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.h>
+#include <aidl/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.h>
+#include <aidl/android/hardware/automotive/vehicle/EvConnectorType.h>
+#include <aidl/android/hardware/automotive/vehicle/EvsServiceState.h>
+#include <aidl/android/hardware/automotive/vehicle/EvsServiceType.h>
+#include <aidl/android/hardware/automotive/vehicle/FuelType.h>
+#include <aidl/android/hardware/automotive/vehicle/GetValueRequest.h>
+#include <aidl/android/hardware/automotive/vehicle/GetValueResult.h>
+#include <aidl/android/hardware/automotive/vehicle/GetValueResults.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2FuelType.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2IgnitionMonitorKind.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2SecondaryAirStatus.h>
+#include <aidl/android/hardware/automotive/vehicle/Obd2SparkIgnitionMonitors.h>
+#include <aidl/android/hardware/automotive/vehicle/PortLocationType.h>
+#include <aidl/android/hardware/automotive/vehicle/SetValueRequest.h>
+#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/VehicleApPowerStateReport.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleArea.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAreaDoor.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAreaSeat.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAreaWheel.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAreaWindow.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleGear.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleHvacFanDirection.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleIgnitionState.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleLightState.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleLightSwitch.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleOilLevel.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropConfig.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropConfigs.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropError.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropValue.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyGroup.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyType.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleSeatOccupancyState.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleTurnSignal.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleUnit.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleVendorPermission.h>
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleHalTypes_H_
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
new file mode 100644
index 0000000..4b2a11a
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_utils_include_VehicleObjectPool_H_
+#define android_hardware_automotive_vehicle_utils_include_VehicleObjectPool_H_
+
+#include <deque>
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include <VehicleHalTypes.h>
+
+#include <android-base/thread_annotations.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// Handy metric mostly for unit tests and debug.
+#define INC_METRIC_IF_DEBUG(val) PoolStats::instance()->val++;
+
+struct PoolStats {
+    std::atomic<uint32_t> Obtained{0};
+    std::atomic<uint32_t> Created{0};
+    std::atomic<uint32_t> Recycled{0};
+    std::atomic<uint32_t> Deleted{0};
+
+    static PoolStats* instance() {
+        static PoolStats inst;
+        return &inst;
+    }
+};
+
+template <typename T>
+struct Deleter {
+    using OnDeleteFunc = std::function<void(T*)>;
+
+    explicit Deleter(const OnDeleteFunc& f) : mOnDelete(f){};
+
+    Deleter() = default;
+    Deleter(const Deleter&) = default;
+
+    void operator()(T* o) { mOnDelete(o); }
+
+  private:
+    OnDeleteFunc mOnDelete;
+};
+
+// This is std::unique_ptr<> with custom delete operation that typically moves the pointer it holds
+// back to ObjectPool.
+template <typename T>
+using recyclable_ptr = typename std::unique_ptr<T, Deleter<T>>;
+
+// Generic abstract object pool class. Users of this class must implement {@Code createObject}.
+//
+// This class is thread-safe. Concurrent calls to {@Code obtain} from multiple threads is OK, also
+// client can obtain an object in one thread and then move ownership to another thread.
+template <typename T>
+class ObjectPool {
+  public:
+    using GetSizeFunc = std::function<size_t(const T&)>;
+
+    ObjectPool(size_t maxPoolObjectsSize, GetSizeFunc getSizeFunc)
+        : mMaxPoolObjectsSize(maxPoolObjectsSize), mGetSizeFunc(getSizeFunc){};
+    virtual ~ObjectPool() = default;
+
+    virtual recyclable_ptr<T> obtain() {
+        std::scoped_lock<std::mutex> lock(mLock);
+        INC_METRIC_IF_DEBUG(Obtained)
+        if (mObjects.empty()) {
+            INC_METRIC_IF_DEBUG(Created)
+            return wrap(createObject());
+        }
+
+        auto o = wrap(mObjects.front().release());
+        mObjects.pop_front();
+        mPoolObjectsSize -= mGetSizeFunc(*o);
+        return o;
+    }
+
+    ObjectPool& operator=(const ObjectPool&) = delete;
+    ObjectPool(const ObjectPool&) = delete;
+
+  protected:
+    virtual T* createObject() = 0;
+
+    virtual void recycle(T* o) {
+        std::scoped_lock<std::mutex> lock(mLock);
+        size_t objectSize = mGetSizeFunc(*o);
+
+        if (objectSize > mMaxPoolObjectsSize ||
+            mPoolObjectsSize > mMaxPoolObjectsSize - objectSize) {
+            INC_METRIC_IF_DEBUG(Deleted)
+
+            // We have no space left in the pool.
+            delete o;
+            return;
+        }
+
+        INC_METRIC_IF_DEBUG(Recycled)
+
+        mObjects.push_back(std::unique_ptr<T>{o});
+        mPoolObjectsSize += objectSize;
+    }
+
+    const size_t mMaxPoolObjectsSize;
+
+  private:
+    const Deleter<T>& getDeleter() {
+        if (!mDeleter.get()) {
+            Deleter<T>* d =
+                    new Deleter<T>(std::bind(&ObjectPool::recycle, this, std::placeholders::_1));
+            mDeleter.reset(d);
+        }
+        return *mDeleter.get();
+    }
+
+    recyclable_ptr<T> wrap(T* raw) { return recyclable_ptr<T>{raw, getDeleter()}; }
+
+    mutable std::mutex mLock;
+    std::deque<std::unique_ptr<T>> mObjects GUARDED_BY(mLock);
+    std::unique_ptr<Deleter<T>> mDeleter;
+    size_t mPoolObjectsSize GUARDED_BY(mLock);
+    GetSizeFunc mGetSizeFunc;
+};
+
+#undef INC_METRIC_IF_DEBUG
+
+// This class provides a pool of recyclable VehiclePropertyValue objects.
+//
+// It has only one overloaded public method - obtain(...), users must call this method when new
+// object is needed with given VehiclePropertyType and vector size (for vector properties). This
+// method returns a recyclable smart pointer to VehiclePropertyValue, essentially this is a
+// std::unique_ptr with custom delete function, so recyclable object has only one owner and
+// developers can safely pass it around. Once this object goes out of scope, it will be returned to
+// the object pool.
+//
+// Some objects are not recyclable: strings and vector data types with vector
+// length > maxRecyclableVectorSize (provided in the constructor). These objects will be deleted
+// immediately once the go out of scope. There's no synchronization penalty for these objects since
+// we do not store them in the pool.
+//
+// This class is thread-safe. Users can obtain an object in one thread and pass it to another.
+//
+// Sample usage:
+//
+//   VehiclePropValuePool pool;
+//   auto v = pool.obtain(VehiclePropertyType::INT32);
+//   v->propId = VehicleProperty::HVAC_FAN_SPEED;
+//   v->areaId = VehicleAreaSeat::ROW_1_LEFT;
+//   v->timestamp = elapsedRealtimeNano();
+//   v->value->int32Values[0] = 42;
+class VehiclePropValuePool {
+  public:
+    using RecyclableType =
+            recyclable_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>;
+
+    // Creates VehiclePropValuePool
+    //
+    // @param maxRecyclableVectorSize - vector value types (e.g. VehiclePropertyType::INT32_VEC)
+    // with size equal or less to this value will be stored in the pool. If users tries to obtain
+    // value with vector size greater than maxRecyclableVectorSize, user will receive a regular
+    // unique pointer instead of a recyclable pointer. The object would not be recycled once it
+    // goes out of scope, but would be deleted.
+    // @param maxPoolObjectsSize - The approximate upper bound of memory each internal recycling
+    // pool could take. We have 4 different type pools, each with 4 different vector size, so
+    // approximately this pool would at-most take 4 * 4 * 10240 = 160k memory.
+    VehiclePropValuePool(size_t maxRecyclableVectorSize = 4, size_t maxPoolObjectsSize = 10240)
+        : mMaxRecyclableVectorSize(maxRecyclableVectorSize),
+          mMaxPoolObjectsSize(maxPoolObjectsSize){};
+
+    // Obtain a recyclable VehiclePropertyValue object from the pool for the given type. If the
+    // given type is not MIXED or STRING, the internal value vector size would be set to 1.
+    // If the given type is MIXED or STRING, all the internal vector sizes would be initialized to
+    // 0.
+    RecyclableType obtain(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type);
+
+    // Obtain a recyclable VehiclePropertyValue object from the pool for the given type. If the
+    // given type is *_VEC or BYTES, the internal value vector size would be set to vectorSize. If
+    // the given type is BOOLEAN, INT32, FLOAT, or INT64, the internal value vector size would be
+    // set to 1. If the given type is MIXED or STRING, all the internal value vector sizes would be
+    // set to 0. vectorSize must be larger than 0.
+    RecyclableType obtain(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+                          size_t vectorSize);
+    // Obtain a recyclable VehicePropertyValue object that is a copy of src. If src does not contain
+    // any value or the src property type is not valid, this function would return an empty
+    // VehiclePropValue.
+    RecyclableType obtain(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& src);
+    // Obtain a recyclable boolean object.
+    RecyclableType obtainBoolean(bool value);
+    // Obtain a recyclable int32 object.
+    RecyclableType obtainInt32(int32_t value);
+    // Obtain a recyclable int64 object.
+    RecyclableType obtainInt64(int64_t value);
+    // Obtain a recyclable float object.
+    RecyclableType obtainFloat(float value);
+    // Obtain a recyclable float object.
+    RecyclableType obtainString(const char* cstr);
+    // Obtain a recyclable mixed object.
+    RecyclableType obtainComplex();
+
+    VehiclePropValuePool(VehiclePropValuePool&) = delete;
+    VehiclePropValuePool& operator=(VehiclePropValuePool&) = delete;
+
+  private:
+    static inline bool isSingleValueType(
+            ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+        return type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::
+                               BOOLEAN ||
+               type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32 ||
+               type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64 ||
+               type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT;
+    }
+
+    static inline bool isComplexType(
+            ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+        return type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED ||
+               type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING;
+    }
+
+    bool isDisposable(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+                      size_t vectorSize) const {
+        return vectorSize > mMaxRecyclableVectorSize || isComplexType(type);
+    }
+
+    RecyclableType obtainDisposable(
+            ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType valueType,
+            size_t vectorSize) const;
+    RecyclableType obtainRecyclable(
+            ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+            size_t vectorSize);
+
+    class InternalPool
+        : public ObjectPool<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> {
+      public:
+        InternalPool(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+                     size_t vectorSize, size_t maxPoolObjectsSize,
+                     ObjectPool::GetSizeFunc getSizeFunc)
+            : ObjectPool(maxPoolObjectsSize, getSizeFunc),
+              mPropType(type),
+              mVectorSize(vectorSize) {}
+
+      protected:
+        ::aidl::android::hardware::automotive::vehicle::VehiclePropValue* createObject() override;
+        void recycle(::aidl::android::hardware::automotive::vehicle::VehiclePropValue* o) override;
+
+      private:
+        bool check(::aidl::android::hardware::automotive::vehicle::RawPropValues* v);
+
+        template <typename VecType>
+        bool check(std::vector<VecType>* vec, bool isVectorType) {
+            return vec->size() == (isVectorType ? mVectorSize : 0);
+        }
+
+      private:
+        ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType mPropType;
+        size_t mVectorSize;
+    };
+    const Deleter<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+            mDisposableDeleter{
+                    [](::aidl::android::hardware::automotive::vehicle::VehiclePropValue* v) {
+                        delete v;
+                    }};
+
+    mutable std::mutex mLock;
+    const size_t mMaxRecyclableVectorSize;
+    const size_t mMaxPoolObjectsSize;
+    // A map with 'property_type' | 'value_vector_size' as key and a recyclable object pool as
+    // value. We would create a recyclable pool for each property type and vector size combination.
+    std::map<int32_t, std::unique_ptr<InternalPool>> mValueTypePools GUARDED_BY(mLock);
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_utils_include_VehicleObjectPool_H_
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h b/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
new file mode 100644
index 0000000..63129e7
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_utils_common_include_VehiclePropertyStore_H_
+#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+
+#include <VehicleHalTypes.h>
+#include <VehicleObjectPool.h>
+#include <android-base/result.h>
+#include <android-base/thread_annotations.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// Encapsulates work related to storing and accessing configuration, storing and modifying
+// vehicle property values.
+//
+// VehiclePropertyValues stored in a sorted map thus it makes easier to get range of values, e.g.
+// to get value for all areas for particular property.
+//
+// This class is thread-safe, however it uses blocking synchronization across all methods.
+class VehiclePropertyStore final {
+  public:
+    explicit VehiclePropertyStore(std::shared_ptr<VehiclePropValuePool> valuePool)
+        : mValuePool(valuePool) {}
+
+    ~VehiclePropertyStore();
+
+    // Callback when a property value has been updated or a new value added.
+    using OnValueChangeCallback = std::function<void(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue&)>;
+
+    // Function that used to calculate unique token for given VehiclePropValue.
+    using TokenFunction = ::std::function<int64_t(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value)>;
+
+    // Register the given property according to the config. A property has to be registered first
+    // before write/read. If tokenFunc is not nullptr, it would be used to generate a unique
+    // property token to act as the key the property store. Otherwise, {propertyID, areaID} would be
+    // used as the key.
+    void registerProperty(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config,
+            TokenFunction tokenFunc = nullptr);
+
+    // Stores provided value. Returns error if config wasn't registered. If 'updateStatus' is
+    // true, the 'status' in 'propValue' would be stored. Otherwise, if this is a new value,
+    // 'status' would be initialized to {@code VehiclePropertyStatus::AVAILABLE}, if this is to
+    // override an existing value, the status for the existing value would be used for the
+    // overridden value.
+    ::android::base::Result<void> writeValue(VehiclePropValuePool::RecyclableType propValue,
+                                             bool updateStatus = false);
+
+    // Remove a given property value from the property store. The 'propValue' would be used to
+    // generate the key for the value to remove.
+    void removeValue(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+
+    // Remove all the values for the property.
+    void removeValuesForProperty(int32_t propId);
+
+    // Read all the stored values.
+    std::vector<VehiclePropValuePool::RecyclableType> readAllValues() const;
+
+    // Read all the values for the property.
+    ::android::base::Result<std::vector<VehiclePropValuePool::RecyclableType>>
+    readValuesForProperty(int32_t propId) const;
+
+    // Read the value for the requested property. Returns {@code StatusCode::NOT_AVAILABLE} if the
+    // value has not been set yet. Returns {@code StatusCode::INVALID_ARG} if the property is
+    // not configured.
+    ::android::base::Result<VehiclePropValuePool::RecyclableType> readValue(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& request) const;
+
+    // Read the value for the requested property. Returns {@code StatusCode::NOT_AVAILABLE} if the
+    // value has not been set yet. Returns {@code StatusCode::INVALID_ARG} if the property is
+    // not configured.
+    ::android::base::Result<VehiclePropValuePool::RecyclableType> readValue(
+            int32_t prop, int32_t area = 0, int64_t token = 0) const;
+
+    // Get all property configs.
+    std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig> getAllConfigs()
+            const;
+
+    // Get the property config for the requested property.
+    ::android::base::Result<
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig*>
+    getConfig(int32_t propId) const;
+
+    // Set a callback that would be called when a property value has been updated.
+    void setOnValueChangeCallback(const OnValueChangeCallback& callback);
+
+    inline std::shared_ptr<VehiclePropValuePool> getValuePool() { return mValuePool; }
+
+  private:
+    struct RecordId {
+        int32_t area;
+        int64_t token;
+
+        std::string toString() const;
+
+        bool operator==(const RecordId& other) const;
+    };
+
+    struct RecordIdHash {
+        size_t operator()(RecordId const& recordId) const;
+    };
+
+    struct Record {
+        ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig propConfig;
+        TokenFunction tokenFunction;
+        std::unordered_map<RecordId, VehiclePropValuePool::RecyclableType, RecordIdHash> values;
+    };
+
+    // {@code VehiclePropValuePool} is thread-safe.
+    std::shared_ptr<VehiclePropValuePool> mValuePool;
+    mutable std::mutex mLock;
+    std::unordered_map<int32_t, Record> mRecordsByPropId GUARDED_BY(mLock);
+    OnValueChangeCallback mOnValueChangeCallback GUARDED_BY(mLock);
+
+    const Record* getRecordLocked(int32_t propId) const;
+
+    Record* getRecordLocked(int32_t propId);
+
+    RecordId getRecordIdLocked(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue,
+            const Record& record) const;
+
+    ::android::base::Result<VehiclePropValuePool::RecyclableType> readValueLocked(
+            const RecordId& recId, const Record& record) const;
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
new file mode 100644
index 0000000..63eb747
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_utils_common_include_VehicleUtils_H_
+#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
+
+#include <VehicleHalTypes.h>
+
+#include <android-base/format.h>
+#include <android-base/result.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// Represents all supported areas for a property.
+constexpr int32_t kAllSupportedAreas = 0;
+
+// Returns underlying (integer) value for given enum.
+template <typename ENUM, typename U = typename std::underlying_type<ENUM>::type>
+inline constexpr U toInt(ENUM const value) {
+    return static_cast<U>(value);
+}
+
+inline constexpr ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType getPropType(
+        int32_t prop) {
+    return static_cast<::aidl::android::hardware::automotive::vehicle::VehiclePropertyType>(
+            prop &
+            toInt(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MASK));
+}
+
+inline constexpr ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup getPropGroup(
+        int32_t prop) {
+    return static_cast<::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup>(
+            prop &
+            toInt(::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup::MASK));
+}
+
+inline constexpr ::aidl::android::hardware::automotive::vehicle::VehicleArea getPropArea(
+        int32_t prop) {
+    return static_cast<::aidl::android::hardware::automotive::vehicle::VehicleArea>(
+            prop & toInt(::aidl::android::hardware::automotive::vehicle::VehicleArea::MASK));
+}
+
+inline constexpr bool isGlobalProp(int32_t prop) {
+    return getPropArea(prop) == ::aidl::android::hardware::automotive::vehicle::VehicleArea::GLOBAL;
+}
+
+inline constexpr bool isSystemProp(int32_t prop) {
+    return ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup::SYSTEM ==
+           getPropGroup(prop);
+}
+
+inline const ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig* getAreaConfig(
+        const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue,
+        const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config) {
+    if (config.areaConfigs.size() == 0) {
+        return nullptr;
+    }
+
+    if (isGlobalProp(propValue.prop)) {
+        return &(config.areaConfigs[0]);
+    }
+
+    for (const auto& c : config.areaConfigs) {
+        if (c.areaId == propValue.areaId) {
+            return &c;
+        }
+    }
+    return nullptr;
+}
+
+inline std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+createVehiclePropValueVec(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+                          size_t vecSize) {
+    auto val = std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>(
+            new ::aidl::android::hardware::automotive::vehicle::VehiclePropValue);
+    switch (type) {
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32:
+            [[fallthrough]];
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BOOLEAN:
+            vecSize = 1;
+            [[fallthrough]];
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32_VEC:
+            val->value.int32Values.resize(vecSize);
+            break;
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT:
+            vecSize = 1;
+            [[fallthrough]];
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT_VEC:
+            val->value.floatValues.resize(vecSize);
+            break;
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64:
+            vecSize = 1;
+            [[fallthrough]];
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64_VEC:
+            val->value.int64Values.resize(vecSize);
+            break;
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BYTES:
+            val->value.byteValues.resize(vecSize);
+            break;
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING:
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED:
+            break;  // Valid, but nothing to do.
+        default:
+            ALOGE("createVehiclePropValue: unknown type: %d", toInt(type));
+            val.reset(nullptr);
+    }
+    return val;
+}
+
+inline std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+createVehiclePropValue(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+    return createVehiclePropValueVec(type, 1);
+}
+
+inline size_t getVehicleRawValueVectorSize(
+        const ::aidl::android::hardware::automotive::vehicle::RawPropValues& value,
+        ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+    switch (type) {
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32:
+            [[fallthrough]];
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BOOLEAN:
+            return std::min(value.int32Values.size(), static_cast<size_t>(1));
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT:
+            return std::min(value.floatValues.size(), static_cast<size_t>(1));
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64:
+            return std::min(value.int64Values.size(), static_cast<size_t>(1));
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32_VEC:
+            return value.int32Values.size();
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT_VEC:
+            return value.floatValues.size();
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64_VEC:
+            return value.int64Values.size();
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BYTES:
+            return value.byteValues.size();
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING:
+            [[fallthrough]];
+        case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED:
+            return 0;
+        default:
+            ALOGE("getVehicleRawValueVectorSize: unknown type: %d", toInt(type));
+            return 0;
+    }
+}
+
+inline void copyVehicleRawValue(
+        ::aidl::android::hardware::automotive::vehicle::RawPropValues* dest,
+        const ::aidl::android::hardware::automotive::vehicle::RawPropValues& src) {
+    dest->int32Values = src.int32Values;
+    dest->floatValues = src.floatValues;
+    dest->int64Values = src.int64Values;
+    dest->byteValues = src.byteValues;
+    dest->stringValue = src.stringValue;
+}
+
+// getVehiclePropValueSize returns approximately how much memory 'value' would take. This should
+// only be used in a limited-size memory pool to set an upper bound for memory consumption.
+inline size_t getVehiclePropValueSize(
+        const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& prop) {
+    size_t size = 0;
+    size += sizeof(prop.timestamp);
+    size += sizeof(prop.areaId);
+    size += sizeof(prop.prop);
+    size += sizeof(prop.status);
+    size += prop.value.int32Values.size() * sizeof(int32_t);
+    size += prop.value.int64Values.size() * sizeof(int64_t);
+    size += prop.value.floatValues.size() * sizeof(float);
+    size += prop.value.byteValues.size() * sizeof(uint8_t);
+    size += prop.value.stringValue.size();
+    return size;
+}
+
+template <class T>
+::aidl::android::hardware::automotive::vehicle::StatusCode getErrorCode(
+        const ::android::base::Result<T>& result) {
+    if (result.ok()) {
+        return ::aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+    }
+    return static_cast<::aidl::android::hardware::automotive::vehicle::StatusCode>(
+            result.error().code());
+}
+
+template <class T>
+int getIntErrorCode(const ::android::base::Result<T>& result) {
+    return toInt(getErrorCode(result));
+}
+
+template <class T>
+std::string getErrorMsg(const ::android::base::Result<T>& result) {
+    if (result.ok()) {
+        return "";
+    }
+    return result.error().message();
+}
+
+template <class T>
+::ndk::ScopedAStatus toScopedAStatus(
+        const ::android::base::Result<T>& result,
+        ::aidl::android::hardware::automotive::vehicle::StatusCode status,
+        std::string additionalErrorMsg) {
+    if (result.ok()) {
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+            toInt(status),
+            fmt::format("{}, error: {}", additionalErrorMsg, getErrorMsg(result)).c_str());
+}
+
+template <class T>
+::ndk::ScopedAStatus toScopedAStatus(
+        const ::android::base::Result<T>& result,
+        ::aidl::android::hardware::automotive::vehicle::StatusCode status) {
+    return toScopedAStatus(result, status, "");
+}
+
+template <class T>
+::ndk::ScopedAStatus toScopedAStatus(const ::android::base::Result<T>& result) {
+    return toScopedAStatus(result, getErrorCode(result));
+}
+
+template <class T>
+::ndk::ScopedAStatus toScopedAStatus(const ::android::base::Result<T>& result,
+                                     std::string additionalErrorMsg) {
+    return toScopedAStatus(result, getErrorCode(result), additionalErrorMsg);
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
new file mode 100644
index 0000000..2480a73
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "VehicleObjectPool"
+
+#include <VehicleObjectPool.h>
+
+#include <VehicleUtils.h>
+
+#include <assert.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(VehiclePropertyType type) {
+    if (isComplexType(type)) {
+        return obtain(type, 0);
+    }
+    return obtain(type, 1);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(VehiclePropertyType type,
+                                                                  size_t vectorSize) {
+    if (isSingleValueType(type)) {
+        vectorSize = 1;
+    } else if (isComplexType(type)) {
+        vectorSize = 0;
+    }
+    return isDisposable(type, vectorSize) ? obtainDisposable(type, vectorSize)
+                                          : obtainRecyclable(type, vectorSize);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(const VehiclePropValue& src) {
+    int propId = src.prop;
+    VehiclePropertyType type = getPropType(propId);
+    size_t vectorSize = getVehicleRawValueVectorSize(src.value, type);
+    if (vectorSize == 0 && !isComplexType(type)) {
+        ALOGW("empty vehicle prop value, contains no content");
+        ALOGW("empty vehicle prop value, contains no content, prop: %d", propId);
+        // Return any empty VehiclePropValue.
+        return RecyclableType{new VehiclePropValue{}, mDisposableDeleter};
+    }
+
+    auto dest = obtain(type, vectorSize);
+
+    dest->prop = propId;
+    dest->areaId = src.areaId;
+    dest->status = src.status;
+    dest->timestamp = src.timestamp;
+    copyVehicleRawValue(&dest->value, src.value);
+
+    return dest;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt32(int32_t value) {
+    auto val = obtain(VehiclePropertyType::INT32);
+    val->value.int32Values[0] = value;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt64(int64_t value) {
+    auto val = obtain(VehiclePropertyType::INT64);
+    val->value.int64Values[0] = value;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainFloat(float value) {
+    auto val = obtain(VehiclePropertyType::FLOAT);
+    val->value.floatValues[0] = value;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainString(const char* cstr) {
+    auto val = obtain(VehiclePropertyType::STRING);
+    val->value.stringValue = cstr;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainComplex() {
+    return obtain(VehiclePropertyType::MIXED);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecyclable(
+        VehiclePropertyType type, size_t vectorSize) {
+    std::scoped_lock<std::mutex> lock(mLock);
+    assert(vectorSize > 0);
+
+    // VehiclePropertyType is not overlapping with vectorSize.
+    int32_t key = static_cast<int32_t>(type) | static_cast<int32_t>(vectorSize);
+    auto it = mValueTypePools.find(key);
+
+    if (it == mValueTypePools.end()) {
+        auto newPool(std::make_unique<InternalPool>(type, vectorSize, mMaxPoolObjectsSize,
+                                                    getVehiclePropValueSize));
+        it = mValueTypePools.emplace(key, std::move(newPool)).first;
+    }
+    return it->second->obtain();
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainBoolean(bool value) {
+    return obtainInt32(value);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainDisposable(
+        VehiclePropertyType valueType, size_t vectorSize) const {
+    return RecyclableType{createVehiclePropValueVec(valueType, vectorSize).release(),
+                          mDisposableDeleter};
+}
+
+void VehiclePropValuePool::InternalPool::recycle(VehiclePropValue* o) {
+    if (o == nullptr) {
+        ALOGE("Attempt to recycle nullptr");
+        return;
+    }
+
+    if (!check(&o->value)) {
+        ALOGE("Discarding value for prop 0x%x because it contains "
+              "data that is not consistent with this pool. "
+              "Expected type: %d, vector size: %zu",
+              o->prop, toInt(mPropType), mVectorSize);
+        delete o;
+    } else {
+        ObjectPool<VehiclePropValue>::recycle(o);
+    }
+}
+
+bool VehiclePropValuePool::InternalPool::check(RawPropValues* v) {
+    return check(&v->int32Values, (VehiclePropertyType::INT32 == mPropType ||
+                                   VehiclePropertyType::INT32_VEC == mPropType ||
+                                   VehiclePropertyType::BOOLEAN == mPropType)) &&
+           check(&v->floatValues, (VehiclePropertyType::FLOAT == mPropType ||
+                                   VehiclePropertyType::FLOAT_VEC == mPropType)) &&
+           check(&v->int64Values, (VehiclePropertyType::INT64 == mPropType ||
+                                   VehiclePropertyType::INT64_VEC == mPropType)) &&
+           check(&v->byteValues, VehiclePropertyType::BYTES == mPropType) &&
+           v->stringValue.size() == 0;
+}
+
+VehiclePropValue* VehiclePropValuePool::InternalPool::createObject() {
+    return createVehiclePropValueVec(mPropType, mVectorSize).release();
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
new file mode 100644
index 0000000..1a79230
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "VehiclePropertyStore"
+#include <utils/Log.h>
+
+#include "VehiclePropertyStore.h"
+
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+#include <android-base/format.h>
+#include <math/HashCombine.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::android::base::Error;
+using ::android::base::Result;
+
+bool VehiclePropertyStore::RecordId::operator==(const VehiclePropertyStore::RecordId& other) const {
+    return area == other.area && token == other.token;
+}
+
+std::string VehiclePropertyStore::RecordId::toString() const {
+    return ::fmt::format("RecordID{{.areaId={:d}, .token={:d}}}", area, token);
+}
+
+size_t VehiclePropertyStore::RecordIdHash::operator()(RecordId const& recordId) const {
+    size_t res = 0;
+    hashCombine(res, recordId.area);
+    hashCombine(res, recordId.token);
+    return res;
+}
+
+VehiclePropertyStore::~VehiclePropertyStore() {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+
+    // Recycling record requires mValuePool, so need to recycle them before destroying mValuePool.
+    mRecordsByPropId.clear();
+    mValuePool.reset();
+}
+
+const VehiclePropertyStore::Record* VehiclePropertyStore::getRecordLocked(int32_t propId) const
+        REQUIRES(mLock) {
+    auto RecordIt = mRecordsByPropId.find(propId);
+    return RecordIt == mRecordsByPropId.end() ? nullptr : &RecordIt->second;
+}
+
+VehiclePropertyStore::Record* VehiclePropertyStore::getRecordLocked(int32_t propId)
+        REQUIRES(mLock) {
+    auto RecordIt = mRecordsByPropId.find(propId);
+    return RecordIt == mRecordsByPropId.end() ? nullptr : &RecordIt->second;
+}
+
+VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked(
+        const VehiclePropValue& propValue, const VehiclePropertyStore::Record& record) const
+        REQUIRES(mLock) {
+    VehiclePropertyStore::RecordId recId{
+            .area = isGlobalProp(propValue.prop) ? 0 : propValue.areaId, .token = 0};
+
+    if (record.tokenFunction != nullptr) {
+        recId.token = record.tokenFunction(propValue);
+    }
+    return recId;
+}
+
+Result<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValueLocked(
+        const RecordId& recId, const Record& record) const REQUIRES(mLock) {
+    if (auto it = record.values.find(recId); it != record.values.end()) {
+        return mValuePool->obtain(*(it->second));
+    }
+    return Error(toInt(StatusCode::NOT_AVAILABLE))
+           << "Record ID: " << recId.toString() << " is not found";
+}
+
+void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
+                                            VehiclePropertyStore::TokenFunction tokenFunc) {
+    std::scoped_lock<std::mutex> g(mLock);
+
+    mRecordsByPropId[config.prop] = Record{
+            .propConfig = config,
+            .tokenFunction = tokenFunc,
+    };
+}
+
+Result<void> VehiclePropertyStore::writeValue(VehiclePropValuePool::RecyclableType propValue,
+                                              bool updateStatus) {
+    std::scoped_lock<std::mutex> g(mLock);
+
+    int32_t propId = propValue->prop;
+
+    VehiclePropertyStore::Record* record = getRecordLocked(propId);
+    if (record == nullptr) {
+        return Error(toInt(StatusCode::INVALID_ARG)) << "property: " << propId << " not registered";
+    }
+
+    if (!isGlobalProp(propId) && getAreaConfig(*propValue, record->propConfig) == nullptr) {
+        return Error(toInt(StatusCode::INVALID_ARG))
+               << "no config for property: " << propId << " area: " << propValue->areaId;
+    }
+
+    VehiclePropertyStore::RecordId recId = getRecordIdLocked(*propValue, *record);
+    bool valueUpdated = true;
+    if (auto it = record->values.find(recId); it != record->values.end()) {
+        const VehiclePropValue* valueToUpdate = it->second.get();
+        int64_t oldTimestamp = valueToUpdate->timestamp;
+        VehiclePropertyStatus oldStatus = valueToUpdate->status;
+        // propValue is outdated and drops it.
+        if (oldTimestamp > propValue->timestamp) {
+            return Error(toInt(StatusCode::INVALID_ARG))
+                   << "outdated timestamp: " << propValue->timestamp;
+        }
+        if (!updateStatus) {
+            propValue->status = oldStatus;
+        }
+
+        valueUpdated = (valueToUpdate->value != propValue->value ||
+                        valueToUpdate->status != propValue->status ||
+                        valueToUpdate->prop != propValue->prop ||
+                        valueToUpdate->areaId != propValue->areaId);
+    } else if (!updateStatus) {
+        propValue->status = VehiclePropertyStatus::AVAILABLE;
+    }
+
+    record->values[recId] = std::move(propValue);
+    if (valueUpdated && mOnValueChangeCallback != nullptr) {
+        mOnValueChangeCallback(*(record->values[recId]));
+    }
+    return {};
+}
+
+void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) {
+    std::scoped_lock<std::mutex> g(mLock);
+
+    VehiclePropertyStore::Record* record = getRecordLocked(propValue.prop);
+    if (record == nullptr) {
+        return;
+    }
+
+    VehiclePropertyStore::RecordId recId = getRecordIdLocked(propValue, *record);
+    if (auto it = record->values.find(recId); it != record->values.end()) {
+        record->values.erase(it);
+    }
+}
+
+void VehiclePropertyStore::removeValuesForProperty(int32_t propId) {
+    std::scoped_lock<std::mutex> g(mLock);
+
+    VehiclePropertyStore::Record* record = getRecordLocked(propId);
+    if (record == nullptr) {
+        return;
+    }
+
+    record->values.clear();
+}
+
+std::vector<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readAllValues() const {
+    std::scoped_lock<std::mutex> g(mLock);
+
+    std::vector<VehiclePropValuePool::RecyclableType> allValues;
+
+    for (auto const& [_, record] : mRecordsByPropId) {
+        for (auto const& [_, value] : record.values) {
+            allValues.push_back(std::move(mValuePool->obtain(*value)));
+        }
+    }
+
+    return allValues;
+}
+
+Result<std::vector<VehiclePropValuePool::RecyclableType>>
+VehiclePropertyStore::readValuesForProperty(int32_t propId) const {
+    std::scoped_lock<std::mutex> g(mLock);
+
+    std::vector<VehiclePropValuePool::RecyclableType> values;
+
+    const VehiclePropertyStore::Record* record = getRecordLocked(propId);
+    if (record == nullptr) {
+        return Error(toInt(StatusCode::INVALID_ARG)) << "property: " << propId << " not registered";
+    }
+
+    for (auto const& [_, value] : record->values) {
+        values.push_back(std::move(mValuePool->obtain(*value)));
+    }
+    return values;
+}
+
+Result<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValue(
+        const VehiclePropValue& propValue) const {
+    std::scoped_lock<std::mutex> g(mLock);
+
+    int32_t propId = propValue.prop;
+    const VehiclePropertyStore::Record* record = getRecordLocked(propId);
+    if (record == nullptr) {
+        return Error(toInt(StatusCode::INVALID_ARG)) << "property: " << propId << " not registered";
+    }
+
+    VehiclePropertyStore::RecordId recId = getRecordIdLocked(propValue, *record);
+    return readValueLocked(recId, *record);
+}
+
+Result<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValue(int32_t propId,
+                                                                             int32_t areaId,
+                                                                             int64_t token) const {
+    std::scoped_lock<std::mutex> g(mLock);
+
+    const VehiclePropertyStore::Record* record = getRecordLocked(propId);
+    if (record == nullptr) {
+        return Error(toInt(StatusCode::INVALID_ARG)) << "property: " << propId << " not registered";
+    }
+
+    VehiclePropertyStore::RecordId recId{.area = isGlobalProp(propId) ? 0 : areaId, .token = token};
+    return readValueLocked(recId, *record);
+}
+
+std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const {
+    std::scoped_lock<std::mutex> g(mLock);
+
+    std::vector<VehiclePropConfig> configs;
+    configs.reserve(mRecordsByPropId.size());
+    for (auto& [_, config] : mRecordsByPropId) {
+        configs.push_back(config.propConfig);
+    }
+    return configs;
+}
+
+Result<const VehiclePropConfig*> VehiclePropertyStore::getConfig(int32_t propId) const {
+    std::scoped_lock<std::mutex> g(mLock);
+
+    const VehiclePropertyStore::Record* record = getRecordLocked(propId);
+    if (record == nullptr) {
+        return Error(toInt(StatusCode::INVALID_ARG)) << "property: " << propId << " not registered";
+    }
+
+    return &record->propConfig;
+}
+
+void VehiclePropertyStore::setOnValueChangeCallback(
+        const VehiclePropertyStore::OnValueChangeCallback& callback) {
+    std::scoped_lock<std::mutex> g(mLock);
+
+    mOnValueChangeCallback = callback;
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/Android.bp b/automotive/vehicle/aidl/impl/utils/common/test/Android.bp
new file mode 100644
index 0000000..dd43712
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/test/Android.bp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "VehicleHalVehicleUtilsTest",
+    srcs: ["*.cpp"],
+    vendor: true,
+    static_libs: [
+        "VehicleHalUtils",
+        "libgtest",
+        "libgmock",
+    ],
+    defaults: ["VehicleHalDefaults"],
+    test_suites: ["device-tests"],
+}
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp
new file mode 100644
index 0000000..a62532c
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <thread>
+
+#include <gtest/gtest.h>
+
+#include <utils/SystemClock.h>
+
+#include <VehicleHalTypes.h>
+#include <VehicleObjectPool.h>
+#include <VehicleUtils.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+struct TestPropertyTypeInfo {
+    VehiclePropertyType type;
+    bool recyclable;
+    size_t vecSize;
+};
+
+std::vector<TestPropertyTypeInfo> getAllPropertyTypes() {
+    return {
+            {
+                    .type = VehiclePropertyType::INT32,
+                    .recyclable = true,
+                    .vecSize = 1,
+            },
+            {
+                    .type = VehiclePropertyType::INT64,
+                    .recyclable = true,
+                    .vecSize = 1,
+            },
+            {
+                    .type = VehiclePropertyType::FLOAT,
+                    .recyclable = true,
+                    .vecSize = 1,
+            },
+            {
+                    .type = VehiclePropertyType::INT32_VEC,
+                    .recyclable = true,
+                    .vecSize = 4,
+            },
+            {
+                    .type = VehiclePropertyType::INT64_VEC,
+                    .recyclable = true,
+                    .vecSize = 4,
+            },
+            {
+                    .type = VehiclePropertyType::FLOAT_VEC,
+                    .recyclable = true,
+                    .vecSize = 4,
+            },
+            {
+                    .type = VehiclePropertyType::BYTES,
+                    .recyclable = true,
+                    .vecSize = 4,
+            },
+            {
+                    .type = VehiclePropertyType::INT32_VEC,
+                    .recyclable = false,
+                    .vecSize = 5,
+            },
+            {
+                    .type = VehiclePropertyType::INT64_VEC,
+                    .recyclable = false,
+                    .vecSize = 5,
+            },
+            {
+                    .type = VehiclePropertyType::FLOAT_VEC,
+                    .recyclable = false,
+                    .vecSize = 5,
+            },
+            {
+                    .type = VehiclePropertyType::BYTES,
+                    .recyclable = false,
+                    .vecSize = 5,
+            },
+            {
+                    .type = VehiclePropertyType::STRING,
+                    .recyclable = false,
+                    .vecSize = 0,
+            },
+            {
+                    .type = VehiclePropertyType::MIXED,
+                    .recyclable = false,
+                    .vecSize = 0,
+            },
+    };
+}
+
+}  // namespace
+
+class VehicleObjectPoolTest : public ::testing::Test {
+  protected:
+    void SetUp() override {
+        mStats = PoolStats::instance();
+        resetStats();
+        mValuePool.reset(new VehiclePropValuePool);
+    }
+
+    void TearDown() override {
+        // At the end, all created objects should be either recycled or deleted.
+        ASSERT_EQ(mStats->Obtained, mStats->Recycled + mStats->Deleted);
+        // Some objects could be recycled multiple times.
+        ASSERT_LE(mStats->Created, mStats->Recycled + mStats->Deleted);
+    }
+
+    PoolStats* mStats;
+    std::unique_ptr<VehiclePropValuePool> mValuePool;
+
+  private:
+    void resetStats() {
+        mStats->Obtained = 0;
+        mStats->Created = 0;
+        mStats->Recycled = 0;
+        mStats->Deleted = 0;
+    }
+};
+
+class VehiclePropertyTypesTest : public VehicleObjectPoolTest,
+                                 public testing::WithParamInterface<TestPropertyTypeInfo> {};
+
+TEST_P(VehiclePropertyTypesTest, testRecycle) {
+    auto info = GetParam();
+    if (!info.recyclable) {
+        GTEST_SKIP();
+    }
+
+    auto value = mValuePool->obtain(info.type, info.vecSize);
+    void* raw = value.get();
+    value.reset();
+    // At this point, value should be recycled and the only object in the pool.
+    ASSERT_EQ(mValuePool->obtain(info.type, info.vecSize).get(), raw);
+
+    ASSERT_EQ(mStats->Obtained, 2u);
+    ASSERT_EQ(mStats->Created, 1u);
+}
+
+TEST_P(VehiclePropertyTypesTest, testNotRecyclable) {
+    auto info = GetParam();
+    if (info.recyclable) {
+        GTEST_SKIP();
+    }
+
+    auto value = mValuePool->obtain(info.type, info.vecSize);
+
+    ASSERT_EQ(mStats->Obtained, 0u) << "Non recyclable object should not be obtained from the pool";
+    ASSERT_EQ(mStats->Created, 0u) << "Non recyclable object should not be created from the pool";
+}
+
+INSTANTIATE_TEST_SUITE_P(AllPropertyTypes, VehiclePropertyTypesTest,
+                         ::testing::ValuesIn(getAllPropertyTypes()));
+
+TEST_F(VehicleObjectPoolTest, testObtainNewObject) {
+    auto value = mValuePool->obtain(VehiclePropertyType::INT32);
+    void* raw = value.get();
+    value.reset();
+    // At this point, value should be recycled and the only object in the pool.
+    ASSERT_EQ(mValuePool->obtain(VehiclePropertyType::INT32).get(), raw);
+    // Obtaining value of another type - should return a new object
+    ASSERT_NE(mValuePool->obtain(VehiclePropertyType::FLOAT).get(), raw);
+
+    ASSERT_EQ(mStats->Obtained, 3u);
+    ASSERT_EQ(mStats->Created, 2u);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainStrings) {
+    mValuePool->obtain(VehiclePropertyType::STRING);
+    auto stringProp = mValuePool->obtain(VehiclePropertyType::STRING);
+    stringProp->value.stringValue = "Hello";
+    void* raw = stringProp.get();
+    stringProp.reset();  // delete the pointer
+
+    auto newStringProp = mValuePool->obtain(VehiclePropertyType::STRING);
+
+    ASSERT_EQ(newStringProp->value.stringValue.size(), 0u);
+    ASSERT_NE(mValuePool->obtain(VehiclePropertyType::STRING).get(), raw);
+    ASSERT_EQ(mStats->Obtained, 0u);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainBoolean) {
+    auto prop = mValuePool->obtainBoolean(true);
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, (VehiclePropValue{
+                             .value = {.int32Values = {1}},
+                     }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainInt32) {
+    auto prop = mValuePool->obtainInt32(1234);
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, (VehiclePropValue{
+                             .value = {.int32Values = {1234}},
+                     }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainInt64) {
+    auto prop = mValuePool->obtainInt64(1234);
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, (VehiclePropValue{
+                             .value = {.int64Values = {1234}},
+                     }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainFloat) {
+    auto prop = mValuePool->obtainFloat(1.234);
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, (VehiclePropValue{
+                             .value = {.floatValues = {1.234}},
+                     }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainString) {
+    auto prop = mValuePool->obtainString("test");
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, (VehiclePropValue{
+                             .value = {.stringValue = "test"},
+                     }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainComplex) {
+    auto prop = mValuePool->obtainComplex();
+
+    ASSERT_NE(prop, nullptr);
+    ASSERT_EQ(*prop, VehiclePropValue{});
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyInt32Values) {
+    VehiclePropValue prop{
+            // INT32_VEC property.
+            .prop = toInt(VehicleProperty::INFO_FUEL_TYPE),
+            .areaId = 2,
+            .timestamp = 3,
+            .value = {.int32Values = {1, 2, 3, 4}},
+    };
+    auto gotValue = mValuePool->obtain(prop);
+
+    ASSERT_NE(gotValue, nullptr);
+    ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyInt64Values) {
+    VehiclePropValue prop{
+            // INT64_VEC property.
+            .prop = toInt(VehicleProperty::WHEEL_TICK),
+            .areaId = 2,
+            .timestamp = 3,
+            .value = {.int64Values = {1, 2, 3, 4}},
+    };
+    auto gotValue = mValuePool->obtain(prop);
+
+    ASSERT_NE(gotValue, nullptr);
+    ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyFloatValues) {
+    VehiclePropValue prop{
+            // FLOAT_VEC property.
+            .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+            .areaId = 2,
+            .timestamp = 3,
+            .value = {.floatValues = {1, 2, 3, 4}},
+    };
+    auto gotValue = mValuePool->obtain(prop);
+
+    ASSERT_NE(gotValue, nullptr);
+    ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyString) {
+    VehiclePropValue prop{
+            // STRING property.
+            .prop = toInt(VehicleProperty::INFO_VIN),
+            .areaId = 2,
+            .timestamp = 3,
+            .value = {.stringValue = "test"},
+    };
+    auto gotValue = mValuePool->obtain(prop);
+
+    ASSERT_NE(gotValue, nullptr);
+    ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyMixed) {
+    VehiclePropValue prop{
+            // MIxed property.
+            .prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE),
+            .areaId = 2,
+            .timestamp = 3,
+            .value =
+                    {
+                            .int32Values = {1, 2, 3},
+                            .floatValues = {4.0, 5.0},
+                            .stringValue = "test",
+                    },
+    };
+    auto gotValue = mValuePool->obtain(prop);
+
+    ASSERT_NE(gotValue, nullptr);
+    ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testMultithreaded) {
+    // In this test we have T threads that concurrently in C cycles
+    // obtain and release O VehiclePropValue objects of FLOAT / INT32 types.
+
+    const int T = 2;
+    const int C = 500;
+    const int O = 100;
+
+    auto poolPtr = mValuePool.get();
+
+    std::vector<std::thread> threads;
+    for (int i = 0; i < T; i++) {
+        threads.push_back(std::thread([&poolPtr]() {
+            for (int j = 0; j < C; j++) {
+                std::vector<recyclable_ptr<VehiclePropValue>> vec;
+                for (int k = 0; k < O; k++) {
+                    vec.push_back(poolPtr->obtain(k % 2 == 0 ? VehiclePropertyType::FLOAT
+                                                             : VehiclePropertyType::INT32));
+                }
+            }
+        }));
+    }
+
+    for (auto& t : threads) {
+        t.join();
+    }
+
+    ASSERT_EQ(mStats->Obtained, static_cast<uint32_t>(T * C * O));
+    ASSERT_EQ(mStats->Recycled + mStats->Deleted, static_cast<uint32_t>(T * C * O));
+    // Created less than obtained in one cycle.
+    ASSERT_LE(mStats->Created, static_cast<uint32_t>(T * O));
+}
+
+TEST_F(VehicleObjectPoolTest, testMemoryLimitation) {
+    std::vector<recyclable_ptr<VehiclePropValue>> vec;
+    for (size_t i = 0; i < 10000; i++) {
+        vec.push_back(mValuePool->obtain(VehiclePropertyType::INT32));
+    }
+    // We have too many values, not all of them would be recycled, some of them will be deleted.
+    vec.clear();
+
+    ASSERT_EQ(mStats->Obtained, 10000u);
+    ASSERT_EQ(mStats->Created, 10000u);
+    ASSERT_GT(mStats->Deleted, 0u) << "expect some values to be deleted, not recycled if too many "
+                                      "values are in the pool";
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
new file mode 100644
index 0000000..1f230e7
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <PropertyUtils.h>
+#include <VehicleHalTypes.h>
+#include <VehiclePropertyStore.h>
+#include <VehicleUtils.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::android::base::Result;
+using ::testing::ElementsAre;
+using ::testing::Eq;
+using ::testing::WhenSortedBy;
+
+constexpr int INVALID_PROP_ID = 0;
+
+struct PropValueCmp {
+    bool operator()(const VehiclePropValue& a, const VehiclePropValue& b) const {
+        return (a.prop < b.prop) || ((a.prop == b.prop) && (a.value < b.value)) ||
+               ((a.prop == b.prop) && (a.value == b.value) && (a.areaId < b.areaId));
+    }
+} propValueCmp;
+
+int64_t timestampToken(const VehiclePropValue& value) {
+    return value.timestamp;
+}
+
+// A helper function to turn value pointer to value structure for easier comparison.
+std::vector<VehiclePropValue> convertValuePtrsToValues(
+        const std::vector<VehiclePropValuePool::RecyclableType>& values) {
+    std::vector<VehiclePropValue> returnValues;
+    returnValues.reserve(values.size());
+    for (auto& value : values) {
+        returnValues.push_back(*value);
+    }
+    return returnValues;
+}
+
+}  // namespace
+
+class VehiclePropertyStoreTest : public ::testing::Test {
+  protected:
+    void SetUp() override {
+        mConfigFuelCapacity = {
+                .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+                .access = VehiclePropertyAccess::READ,
+                .changeMode = VehiclePropertyChangeMode::STATIC,
+        };
+        VehiclePropConfig configTirePressure = {
+                .prop = toInt(VehicleProperty::TIRE_PRESSURE),
+                .access = VehiclePropertyAccess::READ,
+                .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                .areaConfigs = {VehicleAreaConfig{.areaId = WHEEL_FRONT_LEFT},
+                                VehicleAreaConfig{.areaId = WHEEL_FRONT_RIGHT},
+                                VehicleAreaConfig{.areaId = WHEEL_REAR_LEFT},
+                                VehicleAreaConfig{.areaId = WHEEL_REAR_RIGHT}},
+        };
+        mValuePool = std::make_shared<VehiclePropValuePool>();
+        mStore.reset(new VehiclePropertyStore(mValuePool));
+        mStore->registerProperty(mConfigFuelCapacity);
+        mStore->registerProperty(configTirePressure);
+    }
+
+    VehiclePropConfig mConfigFuelCapacity;
+    std::shared_ptr<VehiclePropValuePool> mValuePool;
+    std::unique_ptr<VehiclePropertyStore> mStore;
+};
+
+TEST_F(VehiclePropertyStoreTest, testGetAllConfigs) {
+    std::vector<VehiclePropConfig> configs = mStore->getAllConfigs();
+
+    ASSERT_EQ(configs.size(), static_cast<size_t>(2));
+}
+
+TEST_F(VehiclePropertyStoreTest, testGetConfig) {
+    Result<const VehiclePropConfig*> result =
+            mStore->getConfig(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
+
+    ASSERT_RESULT_OK(result);
+    ASSERT_EQ(*(result.value()), mConfigFuelCapacity);
+}
+
+TEST_F(VehiclePropertyStoreTest, testGetConfigWithInvalidPropId) {
+    Result<const VehiclePropConfig*> result = mStore->getConfig(INVALID_PROP_ID);
+
+    EXPECT_FALSE(result.ok()) << "expect error when getting a config for an invalid property ID";
+    EXPECT_EQ(result.error().code(), toInt(StatusCode::INVALID_ARG));
+}
+
+std::vector<VehiclePropValue> getTestPropValues() {
+    VehiclePropValue fuelCapacity = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+            .value = {.floatValues = {1.0}},
+    };
+
+    VehiclePropValue leftTirePressure = {
+            .prop = toInt(VehicleProperty::TIRE_PRESSURE),
+            .value = {.floatValues = {170.0}},
+            .areaId = WHEEL_FRONT_LEFT,
+    };
+
+    VehiclePropValue rightTirePressure = {
+            .prop = toInt(VehicleProperty::TIRE_PRESSURE),
+            .value = {.floatValues = {180.0}},
+            .areaId = WHEEL_FRONT_RIGHT,
+    };
+
+    return {fuelCapacity, leftTirePressure, rightTirePressure};
+}
+
+TEST_F(VehiclePropertyStoreTest, testWriteValueOk) {
+    auto values = getTestPropValues();
+
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(values[0])));
+}
+
+TEST_F(VehiclePropertyStoreTest, testReadAllValues) {
+    auto values = getTestPropValues();
+    for (const auto& value : values) {
+        ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
+    }
+
+    auto gotValues = mStore->readAllValues();
+
+    ASSERT_THAT(convertValuePtrsToValues(gotValues), WhenSortedBy(propValueCmp, Eq(values)));
+}
+
+TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyOneValue) {
+    auto values = getTestPropValues();
+    for (const auto& value : values) {
+        ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
+    }
+
+    auto result = mStore->readValuesForProperty(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
+
+    ASSERT_RESULT_OK(result);
+    ASSERT_THAT(convertValuePtrsToValues(result.value()), ElementsAre(values[0]));
+}
+
+TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyMultipleValues) {
+    auto values = getTestPropValues();
+    for (const auto& value : values) {
+        ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
+    }
+
+    auto result = mStore->readValuesForProperty(toInt(VehicleProperty::TIRE_PRESSURE));
+
+    ASSERT_RESULT_OK(result);
+    ASSERT_THAT(convertValuePtrsToValues(result.value()),
+                WhenSortedBy(propValueCmp, ElementsAre(values[1], values[2])));
+}
+
+TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyError) {
+    auto result = mStore->readValuesForProperty(INVALID_PROP_ID);
+
+    EXPECT_FALSE(result.ok()) << "expect error when reading values for an invalid property";
+    EXPECT_EQ(result.error().code(), toInt(StatusCode::INVALID_ARG));
+}
+
+TEST_F(VehiclePropertyStoreTest, testReadValueOk) {
+    auto values = getTestPropValues();
+    for (const auto& value : values) {
+        ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
+    }
+
+    VehiclePropValue requestValue = {
+            .prop = toInt(VehicleProperty::TIRE_PRESSURE),
+            .areaId = WHEEL_FRONT_LEFT,
+    };
+
+    auto result = mStore->readValue(requestValue);
+
+    ASSERT_RESULT_OK(result);
+    ASSERT_EQ(*(result.value()), values[1]);
+}
+
+TEST_F(VehiclePropertyStoreTest, testReadValueByPropIdOk) {
+    auto values = getTestPropValues();
+    for (const auto& value : values) {
+        ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
+    }
+
+    auto result = mStore->readValue(toInt(VehicleProperty::TIRE_PRESSURE), WHEEL_FRONT_RIGHT);
+
+    ASSERT_EQ(*(result.value()), values[2]);
+}
+
+TEST_F(VehiclePropertyStoreTest, testReadValueError) {
+    auto values = getTestPropValues();
+    for (const auto& value : values) {
+        ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
+    }
+
+    auto result = mStore->readValue(toInt(VehicleProperty::TIRE_PRESSURE), WHEEL_REAR_LEFT);
+
+    EXPECT_FALSE(result.ok()) << "expect error when reading a value that has not been written";
+    EXPECT_EQ(result.error().code(), toInt(StatusCode::NOT_AVAILABLE));
+}
+
+TEST_F(VehiclePropertyStoreTest, testWriteValueError) {
+    auto v = mValuePool->obtain(VehiclePropertyType::FLOAT);
+    v->prop = INVALID_PROP_ID;
+    v->value.floatValues = {1.0};
+
+    auto result = mStore->writeValue(std::move(v));
+
+    EXPECT_FALSE(result.ok()) << "expect error when writing value for an invalid property ID";
+    EXPECT_EQ(result.error().code(), toInt(StatusCode::INVALID_ARG));
+}
+
+TEST_F(VehiclePropertyStoreTest, testWriteValueNoAreaConfig) {
+    auto v = mValuePool->obtain(VehiclePropertyType::FLOAT);
+    v->prop = toInt(VehicleProperty::TIRE_PRESSURE);
+    v->value.floatValues = {1.0};
+    // There is no config for ALL_WHEELS.
+    v->areaId = ALL_WHEELS;
+
+    auto result = mStore->writeValue(std::move(v));
+
+    EXPECT_FALSE(result.ok()) << "expect error when writing value for an area without config";
+    EXPECT_EQ(result.error().code(), toInt(StatusCode::INVALID_ARG));
+}
+
+TEST_F(VehiclePropertyStoreTest, testWriteOutdatedValue) {
+    auto v = mValuePool->obtain(VehiclePropertyType::FLOAT);
+    v->timestamp = 1;
+    v->prop = toInt(VehicleProperty::TIRE_PRESSURE);
+    v->value.floatValues = {180.0};
+    v->areaId = WHEEL_FRONT_LEFT;
+    ASSERT_RESULT_OK(mStore->writeValue(std::move(v)));
+
+    // Write an older value.
+    auto v2 = mValuePool->obtain(VehiclePropertyType::FLOAT);
+    v2->timestamp = 0;
+    v2->prop = toInt(VehicleProperty::TIRE_PRESSURE);
+    v2->value.floatValues = {180.0};
+    v2->areaId = WHEEL_FRONT_LEFT;
+
+    auto result = mStore->writeValue(std::move(v2));
+
+    EXPECT_FALSE(result.ok()) << "expect error when writing an outdated value";
+    EXPECT_EQ(result.error().code(), toInt(StatusCode::INVALID_ARG));
+}
+
+TEST_F(VehiclePropertyStoreTest, testToken) {
+    int propId = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
+    VehiclePropConfig config = {
+            .prop = propId,
+    };
+
+    // Replace existing config.
+    mStore->registerProperty(config, timestampToken);
+
+    VehiclePropValue fuelCapacityValueToken1 = {
+            .timestamp = 1,
+            .prop = propId,
+            .value = {.floatValues = {1.0}},
+    };
+
+    VehiclePropValue fuelCapacityValueToken2 = {
+            .timestamp = 2,
+            .prop = propId,
+            .value = {.floatValues = {2.0}},
+    };
+
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacityValueToken1)));
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacityValueToken2)));
+
+    auto result = mStore->readValuesForProperty(propId);
+
+    ASSERT_RESULT_OK(result);
+    ASSERT_EQ(result.value().size(), static_cast<size_t>(2));
+
+    auto tokenResult = mStore->readValue(propId, /*areaId=*/0, /*token=*/2);
+
+    ASSERT_RESULT_OK(tokenResult);
+    ASSERT_EQ(*(tokenResult.value()), fuelCapacityValueToken2);
+}
+
+TEST_F(VehiclePropertyStoreTest, testRemoveValue) {
+    auto values = getTestPropValues();
+    for (const auto& value : values) {
+        ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
+    }
+
+    mStore->removeValue(values[0]);
+    auto result = mStore->readValue(values[0]);
+
+    EXPECT_FALSE(result.ok()) << "expect error when reading a removed value";
+    EXPECT_EQ(result.error().code(), toInt(StatusCode::NOT_AVAILABLE));
+
+    auto leftTirePressureResult = mStore->readValue(values[1]);
+
+    ASSERT_RESULT_OK(leftTirePressureResult);
+    ASSERT_EQ(*(leftTirePressureResult.value()), values[1]);
+}
+
+TEST_F(VehiclePropertyStoreTest, testRemoveValuesForProperty) {
+    auto values = getTestPropValues();
+    for (const auto& value : values) {
+        ASSERT_RESULT_OK(mStore->writeValue(std::move(mValuePool->obtain(value))));
+    }
+
+    mStore->removeValuesForProperty(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
+    mStore->removeValuesForProperty(toInt(VehicleProperty::TIRE_PRESSURE));
+
+    auto gotValues = mStore->readAllValues();
+    ASSERT_TRUE(gotValues.empty());
+}
+
+TEST_F(VehiclePropertyStoreTest, testWriteValueUpdateStatus) {
+    VehiclePropValue fuelCapacity = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+            .value = {.floatValues = {1.0}},
+    };
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), true));
+
+    fuelCapacity.status = VehiclePropertyStatus::UNAVAILABLE;
+
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), true));
+
+    VehiclePropValue requestValue = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+    };
+
+    auto result = mStore->readValue(requestValue);
+
+    ASSERT_RESULT_OK(result);
+    ASSERT_EQ(result.value()->status, VehiclePropertyStatus::UNAVAILABLE);
+}
+
+TEST_F(VehiclePropertyStoreTest, testWriteValueNoUpdateStatus) {
+    VehiclePropValue fuelCapacity = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+            .value = {.floatValues = {1.0}},
+    };
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), true));
+
+    fuelCapacity.status = VehiclePropertyStatus::UNAVAILABLE;
+
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), false));
+
+    VehiclePropValue requestValue = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+    };
+
+    auto result = mStore->readValue(requestValue);
+
+    ASSERT_RESULT_OK(result);
+    ASSERT_EQ(result.value()->status, VehiclePropertyStatus::AVAILABLE);
+}
+
+TEST_F(VehiclePropertyStoreTest, testWriteValueNoUpdateStatusForNewValue) {
+    VehiclePropValue fuelCapacity = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+            .value = {.floatValues = {1.0}},
+            .status = VehiclePropertyStatus::UNAVAILABLE,
+    };
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), false));
+
+    VehiclePropValue requestValue = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+    };
+
+    auto result = mStore->readValue(requestValue);
+
+    ASSERT_RESULT_OK(result);
+    ASSERT_EQ(result.value()->status, VehiclePropertyStatus::AVAILABLE);
+}
+
+TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackNewValue) {
+    VehiclePropValue updatedValue;
+    mStore->setOnValueChangeCallback(
+            [&updatedValue](const VehiclePropValue& value) { updatedValue = value; });
+    VehiclePropValue fuelCapacity = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+            .value = {.floatValues = {1.0}},
+    };
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
+
+    ASSERT_EQ(updatedValue, fuelCapacity);
+}
+
+TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackUpdateValue) {
+    VehiclePropValue updatedValue;
+    VehiclePropValue fuelCapacity = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+            .value = {.floatValues = {1.0}},
+    };
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
+
+    mStore->setOnValueChangeCallback(
+            [&updatedValue](const VehiclePropValue& value) { updatedValue = value; });
+
+    fuelCapacity.value.floatValues[0] = 2.0;
+    fuelCapacity.timestamp = 1;
+
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
+
+    ASSERT_EQ(updatedValue, fuelCapacity);
+}
+
+TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackNoUpdate) {
+    VehiclePropValue updatedValue{
+            .prop = INVALID_PROP_ID,
+    };
+    VehiclePropValue fuelCapacity = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+            .value = {.floatValues = {1.0}},
+    };
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
+
+    mStore->setOnValueChangeCallback(
+            [&updatedValue](const VehiclePropValue& value) { updatedValue = value; });
+
+    // Write the same value again should succeed but should not trigger callback.
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
+
+    ASSERT_EQ(updatedValue.prop, INVALID_PROP_ID);
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
new file mode 100644
index 0000000..131eb3b
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <ConcurrentQueue.h>
+#include <PropertyUtils.h>
+#include <VehicleUtils.h>
+
+#include <gtest/gtest.h>
+
+#include <atomic>
+#include <thread>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+TEST(VehicleUtilsTest, testToInt) {
+    int areaGlobal = toInt(VehicleArea::GLOBAL);
+
+    ASSERT_EQ(areaGlobal, 0x01000000);
+}
+
+TEST(VehicleUtilsTest, testGetPropType) {
+    VehiclePropertyType type = getPropType(toInt(VehicleProperty::INFO_VIN));
+
+    ASSERT_EQ(type, VehiclePropertyType::STRING);
+}
+
+TEST(VehicleUtilsTest, testGetPropGroup) {
+    VehiclePropertyGroup group = getPropGroup(toInt(VehicleProperty::INFO_VIN));
+
+    ASSERT_EQ(group, VehiclePropertyGroup::SYSTEM);
+}
+
+TEST(VehicleUtilsTest, testGetPropArea) {
+    VehicleArea area = getPropArea(toInt(VehicleProperty::INFO_VIN));
+
+    ASSERT_EQ(area, VehicleArea::GLOBAL);
+}
+
+TEST(VehicleUtilsTest, testIsGlobalPropTrue) {
+    ASSERT_TRUE(isGlobalProp(toInt(VehicleProperty::INFO_VIN)));
+}
+
+TEST(VehicleUtilsTest, testIsGlobalPropFalse) {
+    ASSERT_FALSE(isGlobalProp(toInt(VehicleProperty::TIRE_PRESSURE)));
+}
+
+TEST(VehicleUtilsTest, testIsSystemPropTrue) {
+    ASSERT_TRUE(isSystemProp(toInt(VehicleProperty::INFO_VIN)));
+}
+
+TEST(VehicleUtilsTest, testIsSystemPropFalse) {
+    // VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+    int vendorProp = 0x0100 + 0x20000000 + 0x01000000 + 0x00100000;
+
+    ASSERT_FALSE(isSystemProp(vendorProp));
+}
+
+TEST(VehicleUtilsTest, testGetAreaConfigGlobal) {
+    VehiclePropValue testPropValue{.prop = toInt(VehicleProperty::INFO_VIN)};
+    VehicleAreaConfig testAreaConfig{.areaId = 0, .minInt32Value = 1};
+    VehiclePropConfig testConfig{.areaConfigs = {testAreaConfig}};
+
+    const VehicleAreaConfig* gotConfig = getAreaConfig(testPropValue, testConfig);
+
+    ASSERT_EQ(*gotConfig, testAreaConfig);
+}
+
+TEST(VehicleUtilsTest, testGetAreaConfigGlobalNoAreaConfig) {
+    VehiclePropValue testPropValue{.prop = toInt(VehicleProperty::INFO_VIN)};
+    VehiclePropConfig testConfig{};
+
+    const VehicleAreaConfig* gotConfig = getAreaConfig(testPropValue, testConfig);
+
+    ASSERT_EQ(gotConfig, nullptr);
+}
+
+TEST(VehicleUtilsTest, testGetAreaConfigNonGlobal) {
+    VehiclePropValue testPropValue = {
+            .prop = toInt(VehicleProperty::TIRE_PRESSURE),
+    };
+    VehicleAreaConfig leftConfig{.areaId = WHEEL_FRONT_LEFT, .minInt32Value = 1};
+    VehicleAreaConfig rightConfig{.areaId = WHEEL_FRONT_RIGHT, .minInt32Value = 2};
+    VehiclePropConfig testConfig{.areaConfigs = {leftConfig, rightConfig}};
+
+    testPropValue.areaId = WHEEL_FRONT_LEFT;
+    const VehicleAreaConfig* gotConfig = getAreaConfig(testPropValue, testConfig);
+
+    ASSERT_EQ(*gotConfig, leftConfig);
+}
+
+TEST(VehicleUtilsTest, testGetAreaConfigNonGlobalNull) {
+    VehiclePropValue testPropValue = {
+            .prop = toInt(VehicleProperty::TIRE_PRESSURE),
+    };
+    VehicleAreaConfig leftConfig{.areaId = WHEEL_FRONT_LEFT, .minInt32Value = 1};
+    VehicleAreaConfig rightConfig{.areaId = WHEEL_FRONT_RIGHT, .minInt32Value = 2};
+    VehiclePropConfig testConfig{.areaConfigs = {leftConfig, rightConfig}};
+
+    // No config for this area.
+    testPropValue.areaId = 0;
+    const VehicleAreaConfig* gotConfig = getAreaConfig(testPropValue, testConfig);
+
+    ASSERT_EQ(gotConfig, nullptr);
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt32) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::INT32);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt32Vec) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValue(VehiclePropertyType::INT32_VEC);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt64) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::INT64);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt64Vec) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValue(VehiclePropertyType::INT64_VEC);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueFloat) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::FLOAT);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueFloatVec) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValue(VehiclePropertyType::FLOAT_VEC);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueBytes) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::BYTES);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.byteValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueString) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::STRING);
+
+    ASSERT_NE(value, nullptr);
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueMixed) {
+    std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::MIXED);
+
+    ASSERT_NE(value, nullptr);
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecInt32) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::INT32, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int32Values.size())
+            << "vector size should always be 1 for single value type";
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueIntVec32Vec) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::INT32_VEC, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(2u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecInt64) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::INT64, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.int64Values.size())
+            << "vector size should always be 1 for single value type";
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueIntVec64Vec) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::INT64_VEC, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(2u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecFloat) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::FLOAT, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(1u, value->value.floatValues.size())
+            << "vector size should always be 1 for single value type";
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueFloatVecMultiValues) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::FLOAT_VEC, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(2u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecBytes) {
+    std::unique_ptr<VehiclePropValue> value =
+            createVehiclePropValueVec(VehiclePropertyType::BYTES, /*vecSize=*/2);
+
+    ASSERT_NE(value, nullptr);
+    ASSERT_EQ(2u, value->value.byteValues.size());
+}
+
+TEST(VehicleUtilsTest, testConcurrentQueueOneThread) {
+    ConcurrentQueue<int> queue;
+
+    queue.push(1);
+    queue.push(2);
+    auto result = queue.flush();
+
+    ASSERT_EQ(result, std::vector<int>({1, 2}));
+}
+
+TEST(VehicleUtilsTest, testConcurrentQueueMultipleThreads) {
+    ConcurrentQueue<int> queue;
+    std::vector<int> results;
+    std::atomic<bool> stop = false;
+
+    std::thread t1([&queue]() {
+        for (int i = 0; i < 100; i++) {
+            queue.push(0);
+        }
+    });
+    std::thread t2([&queue]() {
+        for (int i = 0; i < 100; i++) {
+            queue.push(1);
+        }
+    });
+    std::thread t3([&queue, &results, &stop]() {
+        while (!stop) {
+            queue.waitForItems();
+            for (int i : queue.flush()) {
+                results.push_back(i);
+            }
+        }
+
+        // After we stop, get all the remaining values in the queue.
+        for (int i : queue.flush()) {
+            results.push_back(i);
+        }
+    });
+
+    t1.join();
+    t2.join();
+
+    stop = true;
+    queue.deactivate();
+    t3.join();
+
+    size_t zeroCount = 0;
+    size_t oneCount = 0;
+    for (int i : results) {
+        if (i == 0) {
+            zeroCount++;
+        }
+        if (i == 1) {
+            oneCount++;
+        }
+    }
+
+    EXPECT_EQ(results.size(), static_cast<size_t>(200));
+    EXPECT_EQ(zeroCount, static_cast<size_t>(100));
+    EXPECT_EQ(oneCount, static_cast<size_t>(100));
+}
+
+TEST(VehicleUtilsTest, testConcurrentQueuePushAfterDeactivate) {
+    ConcurrentQueue<int> queue;
+
+    queue.deactivate();
+    queue.push(1);
+
+    ASSERT_TRUE(queue.flush().empty());
+}
+
+TEST(VehicleUtilsTest, testConcurrentQueueDeactivateNotifyWaitingThread) {
+    ConcurrentQueue<int> queue;
+
+    std::thread t([&queue]() {
+        // This would block until queue is deactivated.
+        queue.waitForItems();
+    });
+
+    queue.deactivate();
+
+    t.join();
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/utils/test/Android.bp b/automotive/vehicle/aidl/impl/utils/test/Android.bp
new file mode 100644
index 0000000..ad9954f
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/test/Android.bp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library_headers {
+    name: "VehicleHalTestUtilHeaders",
+    vendor: true,
+    header_libs: ["VehicleHalUtilHeaders"],
+    export_include_dirs: ["include"],
+}
diff --git a/automotive/vehicle/aidl/impl/utils/test/include/TestPropertyUtils.h b/automotive/vehicle/aidl/impl/utils/test/include/TestPropertyUtils.h
new file mode 100644
index 0000000..f80d1e6
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/test/include/TestPropertyUtils.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_utils_test_include_TestPropertyUtils_H_
+#define android_hardware_automotive_vehicle_utils_test_include_TestPropertyUtils_H_
+
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace testpropertyutils_impl {
+
+// These names are not part of the API since we only expose ints.
+using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+
+}  // namespace testpropertyutils_impl
+
+#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+// Converts the system property to the vendor property.
+// WARNING: This is only for the end-to-end testing, Should NOT include in the user build.
+inline constexpr int32_t toVendor(
+        const ::aidl::android::hardware::automotive::vehicle::VehicleProperty& prop) {
+    return (toInt(prop) & ~toInt(testpropertyutils_impl::VehiclePropertyGroup::MASK)) |
+           toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR);
+}
+
+// These properties are used for the end-to-end testing of ClusterHomeService.
+constexpr int32_t VENDOR_CLUSTER_SWITCH_UI =
+        toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_SWITCH_UI);
+constexpr int32_t VENDOR_CLUSTER_DISPLAY_STATE =
+        toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_DISPLAY_STATE);
+constexpr int32_t VENDOR_CLUSTER_REPORT_STATE =
+        toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_REPORT_STATE);
+constexpr int32_t VENDOR_CLUSTER_REQUEST_DISPLAY =
+        toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_REQUEST_DISPLAY);
+constexpr int32_t VENDOR_CLUSTER_NAVIGATION_STATE =
+        toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_NAVIGATION_STATE);
+#endif  // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+
+// These properties are placeholder properties for developers to test new features without
+// implementing a real property.
+constexpr int32_t PLACEHOLDER_PROPERTY_INT =
+        0x2a11 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
+        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
+        toInt(testpropertyutils_impl::VehiclePropertyType::INT32);
+constexpr int32_t PLACEHOLDER_PROPERTY_FLOAT =
+        0x2a11 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
+        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
+        toInt(testpropertyutils_impl::VehiclePropertyType::FLOAT);
+constexpr int32_t PLACEHOLDER_PROPERTY_BOOLEAN =
+        0x2a11 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
+        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
+        toInt(testpropertyutils_impl::VehiclePropertyType::BOOLEAN);
+constexpr int32_t PLACEHOLDER_PROPERTY_STRING =
+        0x2a11 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
+        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
+        toInt(testpropertyutils_impl::VehiclePropertyType::STRING);
+
+// This property is used for test purpose. End to end tests use this property to test set and get
+// method for MIXED type properties.
+constexpr int32_t kMixedTypePropertyForTest =
+        0x1111 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
+        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
+        toInt(testpropertyutils_impl::VehiclePropertyType::MIXED);
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_utils_test_include_TestPropertyUtils_H_
diff --git a/automotive/vehicle/aidl/impl/vhal/Android.bp b/automotive/vehicle/aidl/impl/vhal/Android.bp
new file mode 100644
index 0000000..454fea5
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/Android.bp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_binary {
+    name: "android.hardware.automotive.vehicle@V1-default-service",
+    vendor: true,
+    defaults: [
+        "FakeVehicleHardwareDefaults",
+        "VehicleHalDefaults",
+        "android-automotive-large-parcelable-defaults",
+    ],
+    vintf_fragments: ["vhal-default-service.xml"],
+    init_rc: ["vhal-default-service.rc"],
+    relative_install_path: "hw",
+    srcs: ["src/VehicleService.cpp"],
+    static_libs: [
+        "DefaultVehicleHal",
+        "FakeVehicleHardware",
+        "VehicleHalUtils",
+        "android-automotive-large-parcelable-vendor-lib",
+    ],
+    header_libs: [
+        "IVehicleHardware",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+}
+
+cc_library {
+    name: "DefaultVehicleHal",
+    vendor: true,
+    defaults: [
+        "VehicleHalDefaults",
+        "android-automotive-large-parcelable-defaults",
+    ],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    srcs: [
+        "src/ConnectedClient.cpp",
+        "src/DefaultVehicleHal.cpp",
+    ],
+    static_libs: [
+        "VehicleHalUtils",
+        "android-automotive-large-parcelable-vendor-lib",
+    ],
+    header_libs: [
+        "IVehicleHardware",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+}
diff --git a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
new file mode 100644
index 0000000..43a9603
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_
+#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_
+
+#include <VehicleHalTypes.h>
+
+#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
+#include <android-base/result.h>
+
+#include <memory>
+#include <unordered_set>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// A class to represent a binder client with a callback interface. Each callback function, e.g.
+// GetValues or SetValues for a specific binder client is a separate {@code ConnectedClient}.
+// For one {@code ConnectedClient}, we use one pending request pool to manage all pending requests,
+// so the request IDs must be unique for one client. We also manage a set of callback functions
+// for one client, e.g. timeoutCallback which could be passed to hardware.
+// This class is thread-safe.
+class ConnectedClient {
+  public:
+    ConnectedClient(
+            std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>
+                    callback);
+
+    virtual ~ConnectedClient() = default;
+
+  protected:
+    const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>
+            mCallback;
+};
+
+// A class to represent a client that calls {@code IVehicle.setValues} or {@code
+// IVehicle.getValues}.
+template <class ResultType, class ResultsType>
+class GetSetValuesClient final : public ConnectedClient {
+  public:
+    GetSetValuesClient(
+            std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>
+                    callback);
+
+    // Sends the results to this client.
+    void sendResults(const std::vector<ResultType>& results);
+
+    // Sends each result separately to this client. Each result would be sent through one callback
+    // invocation.
+    void sendResultsSeparately(const std::vector<ResultType>& results);
+
+    // 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();
+
+  private:
+    // The following members are only initialized during construction.
+    std::shared_ptr<const std::function<void(std::vector<ResultType>)>> mResultCallback;
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
new file mode 100644
index 0000000..43bdca2
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_DefaultVehicleHal_H_
+#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_
+
+#include <IVehicleHardware.h>
+#include <LargeParcelableBase.h>
+#include <VehicleUtils.h>
+#include <aidl/android/hardware/automotive/vehicle/BnVehicle.h>
+#include <android/binder_auto_utils.h>
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// private namespace
+namespace defaultvehiclehal_impl {
+
+constexpr int INVALID_MEMORY_FD = -1;
+
+template <class T>
+::ndk::ScopedAStatus toScopedAStatus(
+        const ::android::base::Result<T>& result,
+        ::aidl::android::hardware::automotive::vehicle::StatusCode status) {
+    if (result.ok()) {
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(toInt(status),
+                                                                     getErrorMsg(result).c_str());
+}
+
+template <class T>
+::ndk::ScopedAStatus toScopedAStatus(const ::android::base::Result<T>& result) {
+    return toScopedAStatus(result, getErrorCode(result));
+}
+
+template <class T1, class T2>
+::ndk::ScopedAStatus vectorToStableLargeParcelable(std::vector<T1>& values, T2* output) {
+    auto result = ::android::automotive::car_binder_lib::LargeParcelableBase::
+            parcelableVectorToStableLargeParcelable(values);
+    if (!result.ok()) {
+        return toScopedAStatus(
+                result, ::aidl::android::hardware::automotive::vehicle::StatusCode::INTERNAL_ERROR);
+    }
+    auto& fd = result.value();
+    if (fd == nullptr) {
+        output->payloads = values;
+    } else {
+        // Move the returned ScopedFileDescriptor pointer to ScopedFileDescriptor value in
+        // 'sharedMemoryFd' field.
+        output->sharedMemoryFd.set(fd->get());
+        *(fd->getR()) = INVALID_MEMORY_FD;
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+}  // namespace defaultvehiclehal_impl
+
+class DefaultVehicleHal final : public ::aidl::android::hardware::automotive::vehicle::BnVehicle {
+  public:
+    explicit DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware);
+
+    ::ndk::ScopedAStatus getAllPropConfigs(
+            ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
+            override;
+    ::ndk::ScopedAStatus getValues(
+            const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>&
+                    callback,
+            const ::aidl::android::hardware::automotive::vehicle::GetValueRequests& requests)
+            override;
+    ::ndk::ScopedAStatus setValues(
+            const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>&
+                    callback,
+            const ::aidl::android::hardware::automotive::vehicle::SetValueRequests& requests)
+            override;
+    ::ndk::ScopedAStatus getPropConfigs(
+            const std::vector<int32_t>& props,
+            ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
+            override;
+    ::ndk::ScopedAStatus subscribe(
+            const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>&
+                    callback,
+            const std::vector<::aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
+                    options,
+            int32_t maxSharedMemoryFileCount) override;
+    ::ndk::ScopedAStatus unsubscribe(
+            const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>&
+                    callback,
+            const std::vector<int32_t>& propIds) override;
+    ::ndk::ScopedAStatus returnSharedMemory(
+            const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>&
+                    callback,
+            int64_t sharedMemoryId) override;
+
+    IVehicleHardware* getHardware();
+
+  private:
+    const std::unique_ptr<IVehicleHardware> mVehicleHardware;
+    std::unordered_map<int32_t, ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+            mConfigsByPropId;
+    std::unique_ptr<::ndk::ScopedFileDescriptor> mConfigFile;
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_
diff --git a/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h b/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h
new file mode 100644
index 0000000..dcb15b9
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_
+#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_
+
+#include <LargeParcelableBase.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+
+#include <memory>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+template <class T1, class T2>
+::ndk::ScopedAStatus vectorToStableLargeParcelable(std::vector<T1>&& values, T2* output) {
+    auto result = ::android::automotive::car_binder_lib::LargeParcelableBase::
+            parcelableVectorToStableLargeParcelable(values);
+    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 {
+        // Move the returned ScopedFileDescriptor pointer to ScopedFileDescriptor value in
+        // 'sharedMemoryFd' field.
+        output->sharedMemoryFd = std::move(*fd);
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+template <class T1, class T2>
+::ndk::ScopedAStatus vectorToStableLargeParcelable(const std::vector<T1>& values, T2* output) {
+    // Because 'values' is passed in as const reference, we have to do a copy here.
+    std::vector<T1> valuesCopy = values;
+
+    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);
+
+    if (!result.ok()) {
+        return ::android::base::unexpected(toScopedAStatus(
+                result, ::aidl::android::hardware::automotive::vehicle::StatusCode::INVALID_ARG,
+                "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());
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_
diff --git a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
new file mode 100644
index 0000000..656dfaf
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectedClient.h"
+#include "ParcelableUtils.h"
+
+#include <VehicleHalTypes.h>
+
+#include <utils/Log.h>
+
+#include <inttypes.h>
+#include <unordered_set>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
+using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
+using ::android::base::Result;
+using ::ndk::ScopedAStatus;
+
+// A function to call the specific callback based on results type.
+template <class T>
+ScopedAStatus callCallback(std::shared_ptr<IVehicleCallback> callback, const T& results);
+
+template <>
+ScopedAStatus callCallback<GetValueResults>(std::shared_ptr<IVehicleCallback> callback,
+                                            const GetValueResults& results) {
+    return callback->onGetValues(results);
+}
+
+template <>
+ScopedAStatus callCallback<SetValueResults>(std::shared_ptr<IVehicleCallback> callback,
+                                            const SetValueResults& results) {
+    return callback->onSetValues(results);
+}
+
+// Send a single GetValue/SetValue result through the callback.
+template <class ResultType, class ResultsType>
+void sendGetOrSetValueResult(std::shared_ptr<IVehicleCallback> callback, const ResultType& result) {
+    ResultsType parcelableResults;
+    parcelableResults.payloads.resize(1);
+    parcelableResults.payloads[0] = result;
+    if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults);
+        !callbackStatus.isOk()) {
+        ALOGE("failed to call callback, error: %s, code: %d", callbackStatus.getMessage(),
+              callbackStatus.getServiceSpecificError());
+    }
+}
+
+// Send all the GetValue/SetValue results through callback, one result in each callback invocation.
+template <class ResultType, class ResultsType>
+void sendGetOrSetValueResultsSeparately(std::shared_ptr<IVehicleCallback> callback,
+                                        const std::vector<ResultType>& results) {
+    for (const auto& result : results) {
+        sendGetOrSetValueResult<ResultType, ResultsType>(callback, result);
+    }
+}
+
+// Send all the GetValue/SetValue results through callback in a single callback invocation.
+template <class ResultType, class ResultsType>
+void sendGetOrSetValueResults(std::shared_ptr<IVehicleCallback> callback,
+                              const std::vector<ResultType>& results) {
+    ResultsType parcelableResults;
+    ScopedAStatus status = vectorToStableLargeParcelable(results, &parcelableResults);
+    if (status.isOk()) {
+        if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults);
+            !callbackStatus.isOk()) {
+            ALOGE("failed to call callback, error: %s, code: %d", status.getMessage(),
+                  status.getServiceSpecificError());
+        }
+        return;
+    }
+    int statusCode = status.getServiceSpecificError();
+    ALOGE("failed to marshal result into large parcelable, error: "
+          "%s, code: %d",
+          status.getMessage(), statusCode);
+    sendGetOrSetValueResultsSeparately<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);
+template void sendGetOrSetValueResult<SetValueResult, SetValueResults>(
+        std::shared_ptr<IVehicleCallback> callback, const SetValueResult& result);
+
+template void sendGetOrSetValueResults<GetValueResult, GetValueResults>(
+        std::shared_ptr<IVehicleCallback> callback, const std::vector<GetValueResult>& results);
+template void sendGetOrSetValueResults<SetValueResult, SetValueResults>(
+        std::shared_ptr<IVehicleCallback> callback, const std::vector<SetValueResult>& results);
+
+template void sendGetOrSetValueResultsSeparately<GetValueResult, GetValueResults>(
+        std::shared_ptr<IVehicleCallback> callback, const std::vector<GetValueResult>& results);
+template void sendGetOrSetValueResultsSeparately<SetValueResult, SetValueResults>(
+        std::shared_ptr<IVehicleCallback> callback, const std::vector<SetValueResult>& results);
+
+}  // namespace
+
+ConnectedClient::ConnectedClient(std::shared_ptr<IVehicleCallback> callback)
+    : mCallback(callback) {}
+
+template <class ResultType, class ResultsType>
+GetSetValuesClient<ResultType, ResultsType>::GetSetValuesClient(
+        std::shared_ptr<IVehicleCallback> callback)
+    : ConnectedClient(callback) {
+    mResultCallback = std::make_shared<const std::function<void(std::vector<ResultType>)>>(
+            [callback](std::vector<ResultType> results) {
+                return sendGetOrSetValueResults<ResultType, ResultsType>(callback, results);
+            });
+}
+
+template <class ResultType, class ResultsType>
+std::shared_ptr<const std::function<void(std::vector<ResultType>)>>
+GetSetValuesClient<ResultType, ResultsType>::getResultCallback() {
+    return mResultCallback;
+}
+
+template <class ResultType, class ResultsType>
+void GetSetValuesClient<ResultType, ResultsType>::sendResults(
+        const std::vector<ResultType>& results) {
+    return sendGetOrSetValueResults<ResultType, ResultsType>(mCallback, results);
+}
+
+template <class ResultType, class ResultsType>
+void GetSetValuesClient<ResultType, ResultsType>::sendResultsSeparately(
+        const std::vector<ResultType>& results) {
+    return sendGetOrSetValueResultsSeparately<ResultType, ResultsType>(mCallback, results);
+}
+
+template class GetSetValuesClient<GetValueResult, GetValueResults>;
+template class GetSetValuesClient<SetValueResult, SetValueResults>;
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
new file mode 100644
index 0000000..fd9e331
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DefaultVehicleHal"
+
+#include <DefaultVehicleHal.h>
+
+#include <LargeParcelableBase.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+#include <android-base/result.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
+using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
+using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
+using ::android::automotive::car_binder_lib::LargeParcelableBase;
+using ::android::base::Result;
+using ::ndk::ScopedAStatus;
+
+DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware)
+    : mVehicleHardware(std::move(hardware)) {
+    auto configs = mVehicleHardware->getAllPropertyConfigs();
+    for (auto& config : configs) {
+        mConfigsByPropId[config.prop] = config;
+    }
+    auto result = LargeParcelableBase::parcelableVectorToStableLargeParcelable(configs);
+    if (!result.ok()) {
+        ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
+              getErrorMsg(result).c_str(), getIntErrorCode(result));
+        return;
+    }
+
+    if (result.value() != nullptr) {
+        mConfigFile = std::move(result.value());
+    }
+}
+
+ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
+    if (mConfigFile != nullptr) {
+        output->sharedMemoryFd.set(dup(mConfigFile->get()));
+        return ScopedAStatus::ok();
+    }
+    output->payloads.reserve(mConfigsByPropId.size());
+    for (const auto& [_, config] : mConfigsByPropId) {
+        output->payloads.push_back(config);
+    }
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultVehicleHal::getValues(const std::shared_ptr<IVehicleCallback>&,
+                                           const GetValueRequests&) {
+    // TODO(b/200737967): implement this.
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultVehicleHal::setValues(const std::shared_ptr<IVehicleCallback>&,
+                                           const SetValueRequests&) {
+    // TODO(b/200737967): implement this.
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
+                                                VehiclePropConfigs* output) {
+    std::vector<VehiclePropConfig> configs;
+    for (int32_t prop : props) {
+        if (mConfigsByPropId.find(prop) != mConfigsByPropId.end()) {
+            configs.push_back(mConfigsByPropId[prop]);
+        }
+    }
+    return defaultvehiclehal_impl::vectorToStableLargeParcelable(configs, output);
+}
+
+ScopedAStatus DefaultVehicleHal::subscribe(const std::shared_ptr<IVehicleCallback>&,
+                                           const std::vector<SubscribeOptions>&, int32_t) {
+    // TODO(b/200737967): implement this.
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultVehicleHal::unsubscribe(const std::shared_ptr<IVehicleCallback>&,
+                                             const std::vector<int32_t>&) {
+    // TODO(b/200737967): implement this.
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus DefaultVehicleHal::returnSharedMemory(const std::shared_ptr<IVehicleCallback>&,
+                                                    int64_t) {
+    // TODO(b/200737967): implement this.
+    return ScopedAStatus::ok();
+}
+
+IVehicleHardware* DefaultVehicleHal::getHardware() {
+    return mVehicleHardware.get();
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp b/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
new file mode 100644
index 0000000..c8b5c65
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VehicleService"
+
+#include <DefaultVehicleHal.h>
+#include <FakeVehicleHardware.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <utils/Log.h>
+
+using ::android::hardware::automotive::vehicle::DefaultVehicleHal;
+using ::android::hardware::automotive::vehicle::fake::FakeVehicleHardware;
+
+int main(int /* argc */, char* /* argv */[]) {
+    std::unique_ptr<FakeVehicleHardware> hardware = std::make_unique<FakeVehicleHardware>();
+    std::shared_ptr<DefaultVehicleHal> vhal =
+            ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+
+    ALOGI("Registering as service...");
+    binder_exception_t err = AServiceManager_addService(
+            vhal->asBinder().get(), "android.hardware.automotive.vehicle.IVehicle/default");
+    if (err != EX_NONE) {
+        ALOGE("failed to register android.hardware.automotive.vehicle service, exception: %d", err);
+        return 1;
+    }
+
+    if (!ABinderProcess_setThreadPoolMaxThreadCount(4)) {
+        ALOGE("%s", "failed to set thread pool max thread count");
+        return 1;
+    }
+    ABinderProcess_startThreadPool();
+
+    ALOGI("Vehicle Service Ready");
+
+    ABinderProcess_joinThreadPool();
+
+    ALOGI("Vehicle Service Exiting");
+
+    return 0;
+}
diff --git a/automotive/vehicle/aidl/impl/vhal/test/Android.bp b/automotive/vehicle/aidl/impl/vhal/test/Android.bp
new file mode 100644
index 0000000..bf16475
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/test/Android.bp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "DefaultVehicleHalTest",
+    vendor: true,
+    srcs: ["*.cpp"],
+    static_libs: [
+        "DefaultVehicleHal",
+        "VehicleHalUtils",
+        "android-automotive-large-parcelable-vendor-lib",
+        "libgtest",
+        "libgmock",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "liblog",
+        "libutils",
+    ],
+    header_libs: [
+        "IVehicleHardware",
+    ],
+    defaults: [
+        "VehicleHalDefaults",
+        "android-automotive-large-parcelable-defaults",
+    ],
+    test_suites: ["device-tests"],
+}
diff --git a/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp
new file mode 100644
index 0000000..ddd0c65
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectedClient.h"
+#include "MockVehicleCallback.h"
+
+#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
+using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+class ConnectedClientTest : public ::testing::Test {
+  public:
+    void SetUp() override {
+        mCallback = ndk::SharedRefBase::make<MockVehicleCallback>();
+        mCallbackClient = IVehicleCallback::fromBinder(mCallback->asBinder());
+    }
+
+    std::shared_ptr<IVehicleCallback> getCallbackClient() { return mCallbackClient; }
+
+    MockVehicleCallback* getCallback() { return mCallback.get(); }
+
+  protected:
+    using GetValuesClient = GetSetValuesClient<GetValueResult, GetValueResults>;
+    using SetValuesClient = GetSetValuesClient<SetValueResult, SetValueResults>;
+
+  private:
+    std::shared_ptr<MockVehicleCallback> mCallback;
+    std::shared_ptr<IVehicleCallback> mCallbackClient;
+};
+
+TEST_F(ConnectedClientTest, testSendGetValueResults) {
+    std::vector<GetValueResult> results = {{
+                                                   .requestId = 0,
+                                                   .status = StatusCode::OK,
+                                                   .prop =
+                                                           VehiclePropValue{
+                                                                   .prop = 0,
+                                                           },
+                                           },
+                                           {
+                                                   .requestId = 1,
+                                                   .status = StatusCode::OK,
+                                                   .prop =
+                                                           VehiclePropValue{
+                                                                   .prop = 1,
+                                                           },
+                                           }};
+
+    GetValuesClient client(getCallbackClient());
+
+    client.sendResults(results);
+
+    auto maybeGetValueResults = getCallback()->nextGetValueResults();
+    ASSERT_TRUE(maybeGetValueResults.has_value());
+    ASSERT_EQ(maybeGetValueResults.value().payloads, results);
+}
+
+TEST_F(ConnectedClientTest, testSendGetValueResultsSeparately) {
+    std::vector<GetValueResult> results = {{
+                                                   .requestId = 0,
+                                                   .status = StatusCode::OK,
+                                                   .prop =
+                                                           VehiclePropValue{
+                                                                   .prop = 0,
+                                                           },
+                                           },
+                                           {
+                                                   .requestId = 1,
+                                                   .status = StatusCode::OK,
+                                                   .prop =
+                                                           VehiclePropValue{
+                                                                   .prop = 1,
+                                                           },
+                                           }};
+
+    GetValuesClient client(getCallbackClient());
+
+    client.sendResultsSeparately(results);
+
+    for (auto& result : results) {
+        auto maybeGetValueResults = getCallback()->nextGetValueResults();
+        EXPECT_TRUE(maybeGetValueResults.has_value());
+        if (!maybeGetValueResults.has_value()) {
+            continue;
+        }
+        EXPECT_EQ(maybeGetValueResults.value().payloads, std::vector<GetValueResult>({result}));
+    }
+}
+
+TEST_F(ConnectedClientTest, testGetValuesGnResultCallback) {
+    std::vector<GetValueResult> results = {{
+                                                   .requestId = 0,
+                                                   .status = StatusCode::OK,
+                                                   .prop =
+                                                           VehiclePropValue{
+                                                                   .prop = 0,
+                                                           },
+                                           },
+                                           {
+                                                   .requestId = 1,
+                                                   .status = StatusCode::OK,
+                                                   .prop =
+                                                           VehiclePropValue{
+                                                                   .prop = 1,
+                                                           },
+                                           }};
+
+    GetValuesClient client(getCallbackClient());
+
+    (*(client.getResultCallback()))(results);
+
+    auto maybeGetValueResults = getCallback()->nextGetValueResults();
+    ASSERT_TRUE(maybeGetValueResults.has_value());
+    ASSERT_EQ(maybeGetValueResults.value().payloads, results);
+}
+
+TEST_F(ConnectedClientTest, testSendSetValueResults) {
+    std::vector<SetValueResult> results = {{
+                                                   .requestId = 0,
+                                                   .status = StatusCode::OK,
+                                           },
+                                           {
+                                                   .requestId = 1,
+                                                   .status = StatusCode::OK,
+                                           }};
+
+    SetValuesClient client(getCallbackClient());
+
+    client.sendResults(results);
+
+    auto maybeSetValueResults = getCallback()->nextSetValueResults();
+    ASSERT_TRUE(maybeSetValueResults.has_value());
+    ASSERT_EQ(maybeSetValueResults.value().payloads, results);
+}
+
+TEST_F(ConnectedClientTest, testSendSetValueResultsSeparately) {
+    std::vector<SetValueResult> results = {{
+                                                   .requestId = 0,
+                                                   .status = StatusCode::OK,
+                                           },
+                                           {
+                                                   .requestId = 1,
+                                                   .status = StatusCode::OK,
+                                           }};
+
+    SetValuesClient client(getCallbackClient());
+
+    client.sendResultsSeparately(results);
+
+    for (auto& result : results) {
+        auto maybeSetValueResults = getCallback()->nextSetValueResults();
+        EXPECT_TRUE(maybeSetValueResults.has_value());
+        if (!maybeSetValueResults.has_value()) {
+            continue;
+        }
+        EXPECT_EQ(maybeSetValueResults.value().payloads, std::vector<SetValueResult>({result}));
+    }
+}
+
+TEST_F(ConnectedClientTest, testSetValuesGetResultCallback) {
+    std::vector<SetValueResult> results = {{
+                                                   .requestId = 0,
+                                                   .status = StatusCode::OK,
+                                           },
+                                           {
+                                                   .requestId = 1,
+                                                   .status = StatusCode::OK,
+                                           }};
+
+    SetValuesClient client(getCallbackClient());
+
+    (*(client.getResultCallback()))(results);
+
+    auto maybeSetValueResults = getCallback()->nextSetValueResults();
+    ASSERT_TRUE(maybeSetValueResults.has_value());
+    ASSERT_EQ(maybeSetValueResults.value().payloads, results);
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
new file mode 100644
index 0000000..2b5ca70
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DefaultVehicleHal.h"
+
+#include <IVehicleHardware.h>
+#include <LargeParcelableBase.h>
+#include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
+#include <android-base/thread_annotations.h>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <optional>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
+using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::IVehicle;
+using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+using ::android::automotive::car_binder_lib::LargeParcelableBase;
+using ::android::base::Result;
+
+using ::testing::Eq;
+using ::testing::WhenSortedBy;
+
+class MockVehicleHardware final : public IVehicleHardware {
+  public:
+    std::vector<VehiclePropConfig> getAllPropertyConfigs() const override {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+        return mPropertyConfigs;
+    }
+
+    StatusCode setValues(std::shared_ptr<const SetValuesCallback>,
+                         const std::vector<SetValueRequest>&) override {
+        // TODO(b/200737967): mock this.
+        return StatusCode::OK;
+    }
+
+    StatusCode getValues(std::shared_ptr<const GetValuesCallback>,
+                         const std::vector<GetValueRequest>&) const override {
+        // TODO(b/200737967): mock this.
+        return StatusCode::OK;
+    }
+
+    DumpResult dump(const std::vector<std::string>&) override {
+        // TODO(b/200737967): mock this.
+        return DumpResult{};
+    }
+
+    StatusCode checkHealth() override {
+        // TODO(b/200737967): mock this.
+        return StatusCode::OK;
+    }
+
+    void registerOnPropertyChangeEvent(std::unique_ptr<const PropertyChangeCallback>) override {
+        // TODO(b/200737967): mock this.
+    }
+
+    void registerOnPropertySetErrorEvent(std::unique_ptr<const PropertySetErrorCallback>) override {
+        // TODO(b/200737967): mock this.
+    }
+
+    // Test functions.
+    void setPropertyConfigs(const std::vector<VehiclePropConfig>& configs) {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+        mPropertyConfigs = configs;
+    }
+
+  private:
+    mutable std::mutex mLock;
+    std::vector<VehiclePropConfig> mPropertyConfigs GUARDED_BY(mLock);
+};
+
+struct PropConfigCmp {
+    bool operator()(const VehiclePropConfig& a, const VehiclePropConfig& b) const {
+        return (a.prop < b.prop);
+    }
+} propConfigCmp;
+
+}  // namespace
+
+TEST(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
+    auto testConfigs = std::vector<VehiclePropConfig>({
+            VehiclePropConfig{
+                    .prop = 1,
+            },
+            VehiclePropConfig{
+                    .prop = 2,
+            },
+    });
+
+    auto hardware = std::make_unique<MockVehicleHardware>();
+    hardware->setPropertyConfigs(testConfigs);
+    auto vhal = ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+    std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+    VehiclePropConfigs output;
+    auto status = client->getAllPropConfigs(&output);
+
+    ASSERT_TRUE(status.isOk());
+    ASSERT_THAT(output.payloads, WhenSortedBy(propConfigCmp, Eq(testConfigs)));
+}
+
+TEST(DefaultVehicleHalTest, testGetAllPropConfigsLarge) {
+    std::vector<VehiclePropConfig> testConfigs;
+    // 10000 VehiclePropConfig exceeds 4k memory limit, so it would be sent through shared memory.
+    for (size_t i = 0; i < 10000; i++) {
+        testConfigs.push_back(VehiclePropConfig{
+                .prop = static_cast<int32_t>(i),
+        });
+    }
+
+    auto hardware = std::make_unique<MockVehicleHardware>();
+    hardware->setPropertyConfigs(testConfigs);
+    auto vhal = ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+    std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+    VehiclePropConfigs output;
+    auto status = client->getAllPropConfigs(&output);
+
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(output.payloads.empty());
+    Result<std::optional<std::vector<VehiclePropConfig>>> result =
+            LargeParcelableBase::stableLargeParcelableToParcelableVector<VehiclePropConfig>(
+                    output.sharedMemoryFd);
+    ASSERT_TRUE(result.ok());
+    ASSERT_TRUE(result.value().has_value());
+    ASSERT_EQ(result.value().value(), testConfigs);
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp
new file mode 100644
index 0000000..ca366cd
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MockVehicleCallback.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
+using ::ndk::ScopedAStatus;
+using ::ndk::ScopedFileDescriptor;
+
+template <class T>
+std::optional<T> pop(std::list<T>& items) {
+    if (items.size() > 0) {
+        auto item = std::move(items.front());
+        items.pop_front();
+        return item;
+    }
+    return std::nullopt;
+}
+
+template <class T>
+static ScopedAStatus storeResults(const T& results, std::list<T>* storedResults) {
+    T resultsCopy{
+            .payloads = results.payloads,
+    };
+    int fd = results.sharedMemoryFd.get();
+    if (fd != -1) {
+        resultsCopy.sharedMemoryFd = ScopedFileDescriptor(dup(fd));
+    }
+    storedResults->push_back(std::move(resultsCopy));
+    return ScopedAStatus::ok();
+}
+
+}  // namespace
+
+ScopedAStatus MockVehicleCallback::onGetValues(const GetValueResults& results) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    return storeResults(results, &mGetValueResults);
+}
+
+ScopedAStatus MockVehicleCallback::onSetValues(const SetValueResults& results) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    return storeResults(results, &mSetValueResults);
+}
+
+ScopedAStatus MockVehicleCallback::onPropertyEvent(const VehiclePropValues&, int32_t) {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors&) {
+    return ScopedAStatus::ok();
+}
+
+std::optional<GetValueResults> MockVehicleCallback::nextGetValueResults() {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    return pop(mGetValueResults);
+}
+
+std::optional<SetValueResults> MockVehicleCallback::nextSetValueResults() {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    return pop(mSetValueResults);
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
new file mode 100644
index 0000000..916575a
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_
+#define android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_
+
+#include <VehicleHalTypes.h>
+
+#include <aidl/android/hardware/automotive/vehicle/BnVehicleCallback.h>
+#include <android-base/thread_annotations.h>
+
+#include <list>
+#include <mutex>
+#include <optional>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// MockVehicleCallback is a mock VehicleCallback implementation that simply stores the results.
+class MockVehicleCallback final
+    : public ::aidl::android::hardware::automotive::vehicle::BnVehicleCallback {
+  public:
+    ::ndk::ScopedAStatus onGetValues(
+            const ::aidl::android::hardware::automotive::vehicle::GetValueResults& results)
+            override;
+    ::ndk::ScopedAStatus onSetValues(
+            const ::aidl::android::hardware::automotive::vehicle::SetValueResults& results)
+            override;
+    ::ndk::ScopedAStatus onPropertyEvent(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValues&,
+            int32_t) override;
+    ::ndk::ScopedAStatus onPropertySetError(
+            const ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors&) override;
+
+    // Test functions
+    std::optional<::aidl::android::hardware::automotive::vehicle::GetValueResults>
+    nextGetValueResults();
+    std::optional<::aidl::android::hardware::automotive::vehicle::SetValueResults>
+    nextSetValueResults();
+
+  private:
+    std::mutex mLock;
+    std::list<::aidl::android::hardware::automotive::vehicle::GetValueResults> mGetValueResults
+            GUARDED_BY(mLock);
+    std::list<::aidl::android::hardware::automotive::vehicle::SetValueResults> mSetValueResults
+            GUARDED_BY(mLock);
+};
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_
diff --git a/automotive/vehicle/aidl/impl/vhal/vhal-default-service.rc b/automotive/vehicle/aidl/impl/vhal/vhal-default-service.rc
new file mode 100644
index 0000000..19267cd
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/vhal-default-service.rc
@@ -0,0 +1,4 @@
+service vendor.vehicle-hal-default /vendor/bin/hw/android.hardware.automotive.vehicle@V1-default-service
+    class early_hal
+    user vehicle_network
+    group system inet
diff --git a/automotive/vehicle/aidl/impl/vhal/vhal-default-service.xml b/automotive/vehicle/aidl/impl/vhal/vhal-default-service.xml
new file mode 100644
index 0000000..8d237b8
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/vhal-default-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.automotive.vehicle</name>
+        <transport>hwbinder</transport>
+        <version>1</version>
+        <interface>
+            <name>IVehicle</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/automotive/vehicle/tools/translate_vehicle_props.py b/automotive/vehicle/tools/translate_vehicle_props.py
new file mode 100644
index 0000000..59eb17d
--- /dev/null
+++ b/automotive/vehicle/tools/translate_vehicle_props.py
@@ -0,0 +1,151 @@
+#!/usr/bin/python
+
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Tools to translate VehicleProperty from types.hal into AIDL format.
+   To store it to a file:
+   $ python translate_vehicle_props.py types.hal > VehicleProperty.aidl
+"""
+import re
+import sys
+
+ENUM_TYPE_TO_PARSE = [ "VehiclePropertyType", "VehiclePropertyGroup", "VehicleArea" ]
+VEHICLE_PROP_ENUM = "VehicleProperty"
+
+RE_COMMENT_BEGIN = re.compile("\s*\/\*\*")
+RE_COMMENT_END = re.compile("\s*\*\/")
+RE_COMMENT_SINGLE_LINE = re.compile("\s*\/\*\*.*\*\/")
+
+RE_ENUM_START = re.compile("\s*enum\s*(\w+)\s?.*\{")
+RE_ENUM_END = re.compile("\s*\}\;")
+
+RE_ENUM_ELEMENT = re.compile("\s*(\w+)\s*\=\s*(\w+),")
+
+RE_VEHICLE_PROP_ELEMENT = re.compile("\s*(\w+)\s*\=\s*\(?\s*(\w+)\s*\|?\s*(\w+\:\w+)?\s*\|?\s*(\w+:\w+)?\s*\|?\s*(\w+:\w+)?\s*\)?,")
+
+DBG_COMMENT = False
+DBG_ENUM = False
+
+class HIDLParser:
+    def __init__(self):
+        self.inEnum = False
+        self.currentEnumName = None
+        self.inVehicleProperty = False
+        self.inComment = False
+        self.recentComments = []
+        self.currentType = None
+        self.enumMap = {}
+        self.outputMsg = []
+        self.multilineFormat = []
+        self.outputMsg.append("package android.hardware.automotive.vehicle\n\n")
+
+    def addRecentCommentToMsg(self):
+        self.outputMsg.extend(self.recentComments)
+        self.recentComments = []
+
+    def addToMsg(self, msg):
+        self.outputMsg.append(msg)
+
+    def printOutputMsg(self):
+        msg = "".join(self.outputMsg)
+        print(msg)
+
+    def parseLine(self, line):
+        if self.inComment:
+            self.recentComments.append(line)
+            if RE_COMMENT_END.match(line):
+                self.inComment = False
+                if DBG_COMMENT:
+                    print("Comment end:{}".format(self.recentComments))
+            return
+        elif RE_COMMENT_BEGIN.match(line):
+            self.recentComments = []
+            self.recentComments.append(line)
+            if RE_COMMENT_SINGLE_LINE.match(line):
+                if DBG_COMMENT:
+                    print("Single line Comment:{}".format(self.recentComments))
+                return
+            self.inComment = True
+            if DBG_COMMENT:
+                print("Comment start")
+            return
+
+        if self.inEnum:
+            if RE_ENUM_END.match(line):
+                self.inEnum = False
+                if DBG_ENUM:
+                    print("End enum {}".format(self.currentEnumName))
+            else:
+                matchElement = RE_ENUM_ELEMENT.match(line);
+                if matchElement:
+                    elementName = matchElement.group(1)
+                    elementValue = matchElement.group(2)
+                    self.enumMap[self.currentEnumName + ':' + elementName] = elementValue
+        elif self.inVehicleProperty:
+            if RE_ENUM_END.match(line):
+                self.inVehicleProperty = False
+                self.addToMsg("}\n")
+            else:
+                text = line.strip()
+                if len(text) == 0:
+                    self.multilineFormat = []
+                else:
+                    self.multilineFormat.append(text)
+                    textToMatch = "".join(self.multilineFormat)
+                    match = RE_VEHICLE_PROP_ELEMENT.match(textToMatch)
+                    if match:
+                        self.multilineFormat = []
+                        name = match.group(1)
+                        val = match.group(2)
+                        type1 = match.group(3)
+                        self.addRecentCommentToMsg()
+                        if type1 == None: # one line case
+                            self.addToMsg("    {} = {},\n".format(name, val))
+                        else:
+                            type2 = match.group(4)
+                            type3 = match.group(5)
+                            self.addToMsg("    {} = {} + {} + {} + {}, // {},{},{}\n".\
+                            format(name, val, self.enumMap[type1], self.enumMap[type3],\
+                                self.enumMap[type2], type1, type3, type2))
+        else:
+            matchEnum = RE_ENUM_START.match(line)
+            if matchEnum:
+                enumName = matchEnum.group(1)
+                if enumName in ENUM_TYPE_TO_PARSE:
+                    self.currentEnumName = enumName
+                    self.inEnum = True
+                    if DBG_ENUM:
+                        print("enum {}".format(enumName))
+                elif enumName == VEHICLE_PROP_ENUM:
+                    self.inVehicleProperty = True
+                    self.addRecentCommentToMsg()
+                    self.addToMsg("@Backing(type=\"int\")\nenum VehicleProperty {\n")
+                    if DBG_ENUM:
+                        print("VehicleProperty starts, all enum values {}".format(self.enumMap))
+
+
+def main():
+    if len(sys.argv) != 2:
+        print("Usage: {} types_hal_file".format(sys.argv[0]))
+        sys.exit(1)
+    file_name = sys.argv[1]
+    with open(file_name, 'r') as f:
+        parser = HIDLParser()
+        for line in f.readlines():
+            parser.parseLine(line)
+        parser.printOutputMsg()
+
+if __name__ == "__main__":
+    main()
diff --git a/biometrics/face/aidl/Android.bp b/biometrics/face/aidl/Android.bp
index 54d3ecd..3f53fc8 100644
--- a/biometrics/face/aidl/Android.bp
+++ b/biometrics/face/aidl/Android.bp
@@ -15,13 +15,14 @@
     ],
     imports: [
         "android.hardware.biometrics.common",
-        "android.hardware.common",
+        "android.hardware.common-V2",
         "android.hardware.keymaster",
     ],
     stability: "vintf",
     backend: {
         java: {
             platform_apis: true,
+            srcs_available: true,
         },
         cpp: {
             enabled: false,
diff --git a/biometrics/fingerprint/2.2/default/Android.bp b/biometrics/fingerprint/2.2/default/Android.bp
index f4fb57f..2d262f0 100644
--- a/biometrics/fingerprint/2.2/default/Android.bp
+++ b/biometrics/fingerprint/2.2/default/Android.bp
@@ -25,6 +25,7 @@
         "libhidlbase",
         "libhardware",
         "libutils",
+        "android.hardware.biometrics.fingerprint@2.1",
         "android.hardware.biometrics.fingerprint@2.2",
     ],
 
diff --git a/biometrics/fingerprint/aidl/Android.bp b/biometrics/fingerprint/aidl/Android.bp
index 5295098..c46150e 100644
--- a/biometrics/fingerprint/aidl/Android.bp
+++ b/biometrics/fingerprint/aidl/Android.bp
@@ -26,5 +26,8 @@
             enabled: false,
         },
     },
-    versions: ["1"],
+    versions: [
+        "1",
+        "2",
+    ],
 }
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
new file mode 100644
index 0000000..411cb75
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/.hash
@@ -0,0 +1 @@
+762eb38ce93ea3c7d39a680949cbdbd2371b3f06
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
new file mode 100644
index 0000000..c51aa03
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
@@ -0,0 +1,50 @@
+/*
+ * 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;
+@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,
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl
new file mode 100644
index 0000000..af7bc3c
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/Error.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.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,
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
new file mode 100644
index 0000000..9c208c4
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.fingerprint;
+@Backing(type="byte") @VintfStability
+enum FingerprintSensorType {
+  UNKNOWN = 0,
+  REAR = 1,
+  UNDER_DISPLAY_ULTRASONIC = 2,
+  UNDER_DISPLAY_OPTICAL = 3,
+  POWER_BUTTON = 4,
+  HOME_BUTTON = 5,
+}
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
new file mode 100644
index 0000000..5d3df6f
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/IFingerprint.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.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
new file mode 100644
index 0000000..9934a76
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -0,0 +1,51 @@
+/*
+ * 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
new file mode 100644
index 0000000..3c40ad6
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.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/SensorLocation.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
new file mode 100644
index 0000000..295fde9
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorLocation.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.fingerprint;
+@VintfStability
+parcelable SensorLocation {
+  int displayId;
+  int sensorLocationX;
+  int sensorLocationY;
+  int sensorRadius;
+  String display = "";
+}
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
new file mode 100644
index 0000000..782d289
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/2/android/hardware/biometrics/fingerprint/SensorProps.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.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/SensorLocation.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorLocation.aidl
index 515ddaa..295fde9 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorLocation.aidl
@@ -38,4 +38,5 @@
   int sensorLocationX;
   int sensorLocationY;
   int sensorRadius;
+  String display = "";
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl
index b1618b2..d12605c 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl
@@ -19,15 +19,7 @@
 @VintfStability
 parcelable SensorLocation {
     /**
-     * The display to which the following measurements are relative to. This must correspond to the
-     * android.hardware.DisplayManager#getDisplay Android API.
-     *
-     * A few examples:
-     *   1) A capacitive rear fingerprint sensor would specify the display to which it is behind.
-     *   2) An under-display fingerprint sensor would specify the display on which the sensor is
-     *      located.
-     *   3) A foldable device would specify multiple locations and have a SensorLocation entry
-     *      for each display from which the sensor is accessible from.
+     * Deprecated use the display field instead. This field was never used.
      */
     int displayId;
 
@@ -51,4 +43,18 @@
      * in pixels.
      */
     int sensorRadius;
+
+    /**
+     * The display to which all of the measurements are relative to. This must correspond to the
+     * android.view.Display#getUniqueId Android API. The default display is used if this field is
+     * empty.
+     *
+     * A few examples:
+     *   1) A capacitive rear fingerprint sensor would specify the display to which it is behind.
+     *   2) An under-display fingerprint sensor would specify the display on which the sensor is
+     *      located.
+     *   3) A foldable device would specify multiple locations and have a SensorLocation entry
+     *      for each display from which the sensor is accessible from.
+     */
+    String display = "";
 }
diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp
index 08fe4b0..d4194a3 100644
--- a/biometrics/fingerprint/aidl/default/Android.bp
+++ b/biometrics/fingerprint/aidl/default/Android.bp
@@ -24,7 +24,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.biometrics.fingerprint-V1-ndk",
+        "android.hardware.biometrics.fingerprint-V2-ndk",
         "android.hardware.biometrics.common-V1-ndk",
     ],
 }
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index fbfa52f..1f14de6 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -47,8 +47,9 @@
     common::CommonProps commonProps = {SENSOR_ID, SENSOR_STRENGTH, MAX_ENROLLMENTS_PER_USER,
                                        componentInfo};
 
-    SensorLocation sensorLocation = {0 /* displayId */, 0 /* sensorLocationX */,
-                                     0 /* sensorLocationY */, 0 /* sensorRadius */};
+    SensorLocation sensorLocation = {0 /* displayId (not used) */, 0 /* sensorLocationX */,
+                                     0 /* sensorLocationY */, 0 /* sensorRadius */,
+                                     "" /* display */};
 
     *out = {{commonProps,
              SENSOR_TYPE,
diff --git a/biometrics/fingerprint/aidl/default/fingerprint-default.xml b/biometrics/fingerprint/aidl/default/fingerprint-default.xml
index 89da765..d322eb6 100644
--- a/biometrics/fingerprint/aidl/default/fingerprint-default.xml
+++ b/biometrics/fingerprint/aidl/default/fingerprint-default.xml
@@ -1,6 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.biometrics.fingerprint</name>
+        <version>2</version>
         <fqname>IFingerprint/default</fqname>
     </hal>
 </manifest>
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
new file mode 100644
index 0000000..12eed55
--- /dev/null
+++ b/bluetooth/audio/aidl/Android.bp
@@ -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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.bluetooth.audio",
+    vendor_available: true,
+    srcs: ["android/hardware/bluetooth/audio/*.aidl"],
+    stability: "vintf",
+    imports: [
+        "android.hardware.common-V2",
+        "android.hardware.common.fmq-V1",
+        "android.hardware.audio.common",
+    ],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+            enabled: false,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl
new file mode 100644
index 0000000..ad44c26
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AacCapabilities {
+  android.hardware.bluetooth.audio.AacObjectType objectType;
+  int[] sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  boolean variableBitRateSupported;
+  byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacConfiguration.aidl
new file mode 100644
index 0000000..6adef6d
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacConfiguration.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AacConfiguration {
+  android.hardware.bluetooth.audio.AacObjectType objectType;
+  int sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  boolean variableBitRateEnabled;
+  byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl
new file mode 100644
index 0000000..c129c66
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum AacObjectType {
+  MPEG2_LC = 1,
+  MPEG4_LC = 2,
+  MPEG4_LTP = 4,
+  MPEG4_SCALABLE = 8,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl
new file mode 100644
index 0000000..4767b69
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AptxCapabilities {
+  int[] sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxConfiguration.aidl
new file mode 100644
index 0000000..91e88b3
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxConfiguration.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable AptxConfiguration {
+  int sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl
new file mode 100644
index 0000000..20a7731
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+union AudioCapabilities {
+  android.hardware.bluetooth.audio.PcmCapabilities pcmCapabilities;
+  android.hardware.bluetooth.audio.CodecCapabilities codecCapabilities;
+  android.hardware.bluetooth.audio.LeAudioCapabilities leAudioCapabilities;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl
new file mode 100644
index 0000000..34f7837
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+union AudioConfiguration {
+  android.hardware.bluetooth.audio.PcmConfiguration pcmConfig;
+  android.hardware.bluetooth.audio.CodecConfiguration codecConfig;
+  android.hardware.bluetooth.audio.LeAudioConfiguration leAudioConfig;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioLocation.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioLocation.aidl
new file mode 100644
index 0000000..319a5e2
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioLocation.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum AudioLocation {
+  UNKNOWN = 1,
+  FRONT_LEFT = 2,
+  FRONT_RIGHT = 4,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
new file mode 100644
index 0000000..7c0d825
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum BluetoothAudioStatus {
+  UNKNOWN = 0,
+  SUCCESS = 1,
+  UNSUPPORTED_CODEC_CONFIGURATION = 2,
+  FAILURE = 3,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl
new file mode 100644
index 0000000..b3aa709
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable BroadcastConfiguration {
+  android.hardware.bluetooth.audio.BroadcastConfiguration.BroadcastStreamMap[] streamMap;
+  @VintfStability
+  parcelable BroadcastStreamMap {
+    char streamHandle;
+    int audioChannelAllocation;
+    android.hardware.bluetooth.audio.LeAudioCodecConfiguration leAudioCondecConfig;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl
new file mode 100644
index 0000000..3ca93c3
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum ChannelMode {
+  UNKNOWN = 1,
+  MONO = 2,
+  STEREO = 4,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl
new file mode 100644
index 0000000..b451880
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable CodecCapabilities {
+  android.hardware.bluetooth.audio.CodecType codecType;
+  android.hardware.bluetooth.audio.CodecCapabilities.Capabilities capabilities;
+  @VintfStability
+  union Capabilities {
+    android.hardware.bluetooth.audio.SbcCapabilities sbcCapabilities;
+    android.hardware.bluetooth.audio.AacCapabilities aacCapabilities;
+    android.hardware.bluetooth.audio.LdacCapabilities ldacCapabilities;
+    android.hardware.bluetooth.audio.AptxCapabilities aptxCapabilities;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl
new file mode 100644
index 0000000..863aee2
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable CodecConfiguration {
+  android.hardware.bluetooth.audio.CodecType codecType;
+  int encodedAudioBitrate;
+  int peerMtu;
+  boolean isScmstEnabled;
+  android.hardware.bluetooth.audio.CodecConfiguration.CodecSpecific config;
+  @VintfStability
+  union CodecSpecific {
+    android.hardware.bluetooth.audio.SbcConfiguration sbcConfig;
+    android.hardware.bluetooth.audio.AacConfiguration aacConfig;
+    android.hardware.bluetooth.audio.LdacConfiguration ldacConfig;
+    android.hardware.bluetooth.audio.AptxConfiguration aptxConfig;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecType.aidl
new file mode 100644
index 0000000..44b434b
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecType.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum CodecType {
+  UNKNOWN = 0,
+  SBC = 1,
+  AAC = 2,
+  APTX = 3,
+  APTX_HD = 4,
+  LDAC = 5,
+  LC3 = 6,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
new file mode 100644
index 0000000..9a1557a
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+interface IBluetoothAudioPort {
+  android.hardware.bluetooth.audio.PresentationPosition getPresentationPosition();
+  void startStream();
+  void stopStream();
+  void suspendStream();
+  void updateSourceMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
+  void updateSinkMetadata(in android.hardware.audio.common.SinkMetadata sinkMetadata);
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
new file mode 100644
index 0000000..e5e79cb
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+interface IBluetoothAudioProvider {
+  void endSession();
+  android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> startSession(in android.hardware.bluetooth.audio.IBluetoothAudioPort hostIf, in android.hardware.bluetooth.audio.AudioConfiguration audioConfig);
+  void streamStarted(in android.hardware.bluetooth.audio.BluetoothAudioStatus status);
+  void streamSuspended(in android.hardware.bluetooth.audio.BluetoothAudioStatus status);
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
new file mode 100644
index 0000000..5e33deb
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+interface IBluetoothAudioProviderFactory {
+  android.hardware.bluetooth.audio.AudioCapabilities[] getProviderCapabilities(in android.hardware.bluetooth.audio.SessionType sessionType);
+  android.hardware.bluetooth.audio.IBluetoothAudioProvider openProvider(in android.hardware.bluetooth.audio.SessionType sessionType);
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
new file mode 100644
index 0000000..3c650da
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable Lc3Capabilities {
+  byte[] pcmBitDepth;
+  int[] samplingFrequencyHz;
+  int[] frameDurationUs;
+  int[] octetsPerFrame;
+  byte[] blocksPerSdu;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl
new file mode 100644
index 0000000..ef77da7
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable Lc3Configuration {
+  byte pcmBitDepth;
+  int samplingFrequencyHz;
+  int frameDurationUs;
+  int octetsPerFrame;
+  byte blocksPerSdu;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl
new file mode 100644
index 0000000..19e041a
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable LdacCapabilities {
+  int[] sampleRateHz;
+  android.hardware.bluetooth.audio.LdacChannelMode channelMode;
+  android.hardware.bluetooth.audio.LdacQualityIndex qualityIndex;
+  byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl
new file mode 100644
index 0000000..a9d6c5e
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum LdacChannelMode {
+  UNKNOWN = 1,
+  STEREO = 2,
+  DUAL = 4,
+  MONO = 8,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacConfiguration.aidl
new file mode 100644
index 0000000..8a37638
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable LdacConfiguration {
+  int sampleRateHz;
+  android.hardware.bluetooth.audio.LdacChannelMode channelMode;
+  android.hardware.bluetooth.audio.LdacQualityIndex qualityIndex;
+  byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
new file mode 100644
index 0000000..693392f
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum LdacQualityIndex {
+  HIGH = 1,
+  MID = 2,
+  LOW = 4,
+  ABR = 8,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCapabilities.aidl
new file mode 100644
index 0000000..a7224ca
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCapabilities.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable LeAudioCapabilities {
+  android.hardware.bluetooth.audio.LeAudioMode mode;
+  android.hardware.bluetooth.audio.CodecType codecType;
+  android.hardware.bluetooth.audio.AudioLocation supportedChannel;
+  int supportedChannelCount;
+  android.hardware.bluetooth.audio.LeAudioCapabilities.LeAudioCodecCapabilities leAudioCodecCapabilities;
+  @VintfStability
+  parcelable VendorCapabilities {
+    ParcelableHolder extension;
+  }
+  @VintfStability
+  union LeAudioCodecCapabilities {
+    android.hardware.bluetooth.audio.Lc3Capabilities lc3Capabilities;
+    android.hardware.bluetooth.audio.LeAudioCapabilities.VendorCapabilities vendorCapabillities;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
new file mode 100644
index 0000000..bb3d7e4
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+union LeAudioCodecConfiguration {
+  android.hardware.bluetooth.audio.Lc3Configuration lc3Config;
+  android.hardware.bluetooth.audio.LeAudioCodecConfiguration.VendorConfiguration vendorConfig;
+  @VintfStability
+  parcelable VendorConfiguration {
+    ParcelableHolder extension;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
new file mode 100644
index 0000000..2bc1791
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable LeAudioConfiguration {
+  android.hardware.bluetooth.audio.LeAudioMode mode;
+  android.hardware.bluetooth.audio.LeAudioConfiguration.LeAudioModeConfig modeConfig;
+  android.hardware.bluetooth.audio.CodecType codecType;
+  @VintfStability
+  union LeAudioModeConfig {
+    android.hardware.bluetooth.audio.UnicastConfiguration unicastConfig;
+    android.hardware.bluetooth.audio.BroadcastConfiguration broadcastConfig;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioMode.aidl
new file mode 100644
index 0000000..766f637
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum LeAudioMode {
+  UNKNOWN = 0,
+  UNICAST = 1,
+  BROADCAST = 2,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl
new file mode 100644
index 0000000..6cfe5cd
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable PcmCapabilities {
+  int[] sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  byte[] bitsPerSample;
+  int[] dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmConfiguration.aidl
new file mode 100644
index 0000000..93d7805
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable PcmConfiguration {
+  int sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  byte bitsPerSample;
+  int dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PresentationPosition.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PresentationPosition.aidl
new file mode 100644
index 0000000..7e997e8
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PresentationPosition.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable PresentationPosition {
+  long remoteDeviceAudioDelayNanos;
+  long transmittedOctets;
+  android.hardware.bluetooth.audio.PresentationPosition.TimeSpec transmittedOctetsTimestamp;
+  @VintfStability
+  parcelable TimeSpec {
+    long tvSec;
+    long tvNSec;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
new file mode 100644
index 0000000..5170f16
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum SbcAllocMethod {
+  ALLOC_MD_S = 1,
+  ALLOC_MD_L = 2,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl
new file mode 100644
index 0000000..ec3aa0f
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable SbcCapabilities {
+  int[] sampleRateHz;
+  android.hardware.bluetooth.audio.SbcChannelMode channelMode;
+  byte[] blockLength;
+  byte[] numSubbands;
+  android.hardware.bluetooth.audio.SbcAllocMethod allocMethod;
+  byte[] bitsPerSample;
+  int minBitpool;
+  int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl
new file mode 100644
index 0000000..88fca4a
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum SbcChannelMode {
+  UNKNOWN = 1,
+  JOINT_STEREO = 2,
+  STEREO = 4,
+  DUAL = 8,
+  MONO = 16,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcConfiguration.aidl
new file mode 100644
index 0000000..8eab9c3
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcConfiguration.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable SbcConfiguration {
+  int sampleRateHz;
+  android.hardware.bluetooth.audio.SbcChannelMode channelMode;
+  byte blockLength;
+  byte numSubbands;
+  android.hardware.bluetooth.audio.SbcAllocMethod allocMethod;
+  byte bitsPerSample;
+  int minBitpool;
+  int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl
new file mode 100644
index 0000000..72d7fb2
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum SessionType {
+  UNKNOWN = 0,
+  A2DP_SOFTWARE_ENCODING_DATAPATH = 1,
+  A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH = 2,
+  HEARING_AID_SOFTWARE_ENCODING_DATAPATH = 3,
+  LE_AUDIO_SOFTWARE_ENCODING_DATAPATH = 4,
+  LE_AUDIO_SOFTWARE_DECODING_DATAPATH = 5,
+  LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH = 6,
+  LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH = 7,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastConfiguration.aidl
new file mode 100644
index 0000000..b385763
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastConfiguration.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable UnicastConfiguration {
+  android.hardware.bluetooth.audio.UnicastConfiguration.UnicastStreamMap[] streamMap;
+  int peerDelay;
+  android.hardware.bluetooth.audio.LeAudioCodecConfiguration leAudioCodecConfig;
+  @VintfStability
+  parcelable UnicastStreamMap {
+    char streamHandle;
+    int audioChannelAllocation;
+  }
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl
new file mode 100644
index 0000000..4303883
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AacObjectType;
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AAC codec capabilities
+ */
+@VintfStability
+parcelable AacCapabilities {
+    /* bitfield */
+    AacObjectType objectType;
+    int[] sampleRateHz;
+    /* bitfield */
+    ChannelMode channelMode;
+    boolean variableBitRateSupported;
+    byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacConfiguration.aidl
new file mode 100644
index 0000000..30338e7
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacConfiguration.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AacObjectType;
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AAC codec configuration
+ */
+@VintfStability
+parcelable AacConfiguration {
+    AacObjectType objectType;
+    int sampleRateHz;
+    ChannelMode channelMode;
+    boolean variableBitRateEnabled;
+    byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl
new file mode 100644
index 0000000..480e422
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum AacObjectType {
+    /**
+     * MPEG-2 Low Complexity. Support is Mandatory.
+     */
+    MPEG2_LC = 1,
+    /**
+     * MPEG-4 Low Complexity. Support is Optional.
+     */
+    MPEG4_LC = 1 << 1,
+    /**
+     * MPEG-4 Long Term Prediction. Support is Optional.
+     */
+    MPEG4_LTP = 1 << 2,
+    /**
+     * MPEG-4 Scalable. Support is Optional.
+     */
+    MPEG4_SCALABLE = 1 << 3,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl
new file mode 100644
index 0000000..6a37fc6
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AptX and AptX-HD codec capabilities
+ */
+@VintfStability
+parcelable AptxCapabilities {
+    int[] sampleRateHz;
+    /* bitfield */
+    ChannelMode channelMode;
+    byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxConfiguration.aidl
new file mode 100644
index 0000000..83b7b0c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxConfiguration.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AptX and AptX-HD codec configuration
+ */
+@VintfStability
+parcelable AptxConfiguration {
+    int sampleRateHz;
+    ChannelMode channelMode;
+    byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl
new file mode 100644
index 0000000..6ed4472
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.CodecCapabilities;
+import android.hardware.bluetooth.audio.LeAudioCapabilities;
+import android.hardware.bluetooth.audio.PcmCapabilities;
+
+/**
+ * Used to specify the capabilities of the different session types
+ */
+@VintfStability
+union AudioCapabilities {
+    PcmCapabilities pcmCapabilities;
+    CodecCapabilities codecCapabilities;
+    LeAudioCapabilities leAudioCapabilities;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl
new file mode 100644
index 0000000..ce515b5
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.CodecConfiguration;
+import android.hardware.bluetooth.audio.LeAudioConfiguration;
+import android.hardware.bluetooth.audio.PcmConfiguration;
+
+/**
+ * Used to configure either a Hardware or Software Encoding session based on session type
+ */
+@VintfStability
+union AudioConfiguration {
+    PcmConfiguration pcmConfig;
+    CodecConfiguration codecConfig;
+    LeAudioConfiguration leAudioConfig;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioLocation.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioLocation.aidl
new file mode 100644
index 0000000..dedfbf9
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioLocation.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum AudioLocation {
+    UNKNOWN = 1,
+    FRONT_LEFT = 1 << 1,
+    FRONT_RIGHT = 1 << 2,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
new file mode 100644
index 0000000..ec78445
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum BluetoothAudioStatus {
+    UNKNOWN = 0,
+    SUCCESS = 1,
+    UNSUPPORTED_CODEC_CONFIGURATION = 2,
+    // General failure
+    FAILURE = 3
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl
new file mode 100644
index 0000000..07d05f1
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastConfiguration.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.LeAudioCodecConfiguration;
+
+@VintfStability
+parcelable BroadcastConfiguration {
+    @VintfStability
+    parcelable BroadcastStreamMap {
+        /*
+         * The connection handle used for a unicast or a broadcast group.
+         * Range: 0x0000 to 0xEFFF
+         */
+        char streamHandle;
+        /*
+         * Audio channel allocation is  a bit field, each enabled bit means that given audio
+         * direction, i.e. "left", or "right" is used. Ordering of audio channels comes from the
+         * least significant bit to the most significant bit.
+         */
+        int audioChannelAllocation;
+        LeAudioCodecConfiguration leAudioCondecConfig;
+    }
+    BroadcastStreamMap[] streamMap;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl
new file mode 100644
index 0000000..2df879d
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum ChannelMode {
+    UNKNOWN = 1,
+    MONO = 1 << 1,
+    STEREO = 1 << 2,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl
new file mode 100644
index 0000000..0eee8cb
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AacCapabilities;
+import android.hardware.bluetooth.audio.AptxCapabilities;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.LdacCapabilities;
+import android.hardware.bluetooth.audio.SbcCapabilities;
+
+/**
+ * Used to specify the capabilities of the codecs supported by Hardware Encoding.
+ * AptX and AptX-HD both use the AptxCapabilities field.
+ */
+@VintfStability
+parcelable CodecCapabilities {
+    @VintfStability
+    union Capabilities {
+        SbcCapabilities sbcCapabilities;
+        AacCapabilities aacCapabilities;
+        LdacCapabilities ldacCapabilities;
+        AptxCapabilities aptxCapabilities;
+    }
+    CodecType codecType;
+    Capabilities capabilities;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl
new file mode 100644
index 0000000..fac90f0
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AacConfiguration;
+import android.hardware.bluetooth.audio.AptxConfiguration;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.LdacConfiguration;
+import android.hardware.bluetooth.audio.SbcConfiguration;
+
+/**
+ * Used to configure a Hardware Encoding session.
+ * AptX and AptX-HD both use the AptxConfiguration field.
+ */
+@VintfStability
+parcelable CodecConfiguration {
+    @VintfStability
+    union CodecSpecific {
+        SbcConfiguration sbcConfig;
+        AacConfiguration aacConfig;
+        LdacConfiguration ldacConfig;
+        AptxConfiguration aptxConfig;
+    }
+    CodecType codecType;
+    /**
+     * The encoded audio bitrate in bits / second.
+     * 0x00000000 - The audio bitrate is not specified / unused
+     * 0x00000001 - 0x00FFFFFF - Encoded audio bitrate in bits/second
+     * 0x01000000 - 0xFFFFFFFF - Reserved
+     *
+     * The HAL needs to support all legal bitrates for the selected codec.
+     */
+    int encodedAudioBitrate;
+    /**
+     * Peer MTU (in two-octets)
+     */
+    int peerMtu;
+    /**
+     * Content protection by SCMS-T
+     */
+    boolean isScmstEnabled;
+    CodecSpecific config;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecType.aidl
new file mode 100644
index 0000000..68c60f5
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecType.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum CodecType {
+    UNKNOWN,
+    SBC,
+    AAC,
+    APTX,
+    APTX_HD,
+    LDAC,
+    LC3,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
new file mode 100644
index 0000000..827f57d
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.audio.common.SinkMetadata;
+import android.hardware.audio.common.SourceMetadata;
+import android.hardware.bluetooth.audio.PresentationPosition;
+
+/**
+ * HAL interface from the Audio HAL to the Bluetooth stack
+ *
+ * The Audio HAL calls methods in this interface to start, suspend, and stop
+ * an audio stream. These calls return immediately and the results, if any,
+ * are sent over the IBluetoothAudioProvider interface.
+ *
+ * Moreover, the Audio HAL can also get the presentation position of the stream
+ * and provide stream metadata.
+ *
+ */
+@VintfStability
+interface IBluetoothAudioPort {
+    /**
+     * Get the audio presentation position.
+     *
+     * @return the audio presentation position
+     *
+     */
+    PresentationPosition getPresentationPosition();
+
+    /**
+     * This indicates that the caller of this method has opened the data path
+     * and wants to start an audio stream. The caller must wait for a
+     * IBluetoothAudioProvider.streamStarted(Status) call.
+     */
+    void startStream();
+
+    /**
+     * This indicates that the caller of this method wants to stop the audio
+     * stream. The data path will be closed after this call. There is no
+     * callback from the IBluetoothAudioProvider interface even though the
+     * teardown is asynchronous.
+     */
+    void stopStream();
+
+    /**
+     * This indicates that the caller of this method wants to suspend the audio
+     * stream. The caller must wait for the Bluetooth process to call
+     * IBluetoothAudioProvider.streamSuspended(Status). The caller still keeps
+     * the data path open.
+     */
+    void suspendStream();
+
+    /**
+     * Called when the metadata of the stream's source has been changed.
+     *
+     * @param sourceMetadata Description of the audio that is played by the
+     *    clients.
+     */
+    void updateSourceMetadata(in SourceMetadata sourceMetadata);
+
+    /**
+     * Called when the metadata of the stream's sink has been changed.
+     *
+     * @param sinkMetadata as passed from Audio Framework
+     */
+    void updateSinkMetadata(in SinkMetadata sinkMetadata);
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
new file mode 100644
index 0000000..a2c5ae9
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AudioConfiguration;
+import android.hardware.bluetooth.audio.BluetoothAudioStatus;
+import android.hardware.bluetooth.audio.IBluetoothAudioPort;
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+
+/**
+ * HAL interface from the Bluetooth stack to the Audio HAL
+ *
+ * The Bluetooth stack calls methods in this interface to start and end audio
+ * sessions and sends callback events to the Audio HAL.
+ *
+ */
+@VintfStability
+interface IBluetoothAudioProvider {
+    /**
+     * Ends the current session and unregisters the IBluetoothAudioPort
+     * interface.
+     */
+    void endSession();
+
+    /**
+     * This method indicates that the Bluetooth stack is ready to stream audio.
+     * It registers an instance of IBluetoothAudioPort with and provides the
+     * current negotiated codec to the Audio HAL. After this method is called,
+     * the Audio HAL can invoke IBluetoothAudioPort.startStream().
+     *
+     * Note: endSession() must be called to unregister this IBluetoothAudioPort
+     *
+     * @param hostIf An instance of IBluetoothAudioPort for stream control
+     * @param audioConfig The audio configuration negotiated with the remote
+     *    device. The PCM parameters are set if software based encoding,
+     *    otherwise the correct codec configuration is used for hardware
+     *    encoding.
+     *
+     * @return The fast message queue for audio data from/to this
+     *    provider. Audio data will be in PCM format as specified by the
+     *    audioConfig.pcmConfig parameter. Invalid if streaming is offloaded
+     *    from/to hardware or on failure
+     */
+    MQDescriptor<byte, SynchronizedReadWrite> startSession(
+            in IBluetoothAudioPort hostIf, in AudioConfiguration audioConfig);
+
+    /**
+     * Callback for IBluetoothAudioPort.startStream()
+     *
+     * @param status true for SUCCESS or false for FAILURE
+     */
+    void streamStarted(in BluetoothAudioStatus status);
+
+    /**
+     * Callback for IBluetoothAudioPort.suspendStream()
+     *
+     * @param status true for SUCCESS or false for FAILURE
+     */
+    void streamSuspended(in BluetoothAudioStatus status);
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
new file mode 100644
index 0000000..3cde22c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AudioCapabilities;
+import android.hardware.bluetooth.audio.IBluetoothAudioProvider;
+import android.hardware.bluetooth.audio.SessionType;
+/**
+ * This factory allows a HAL implementation to be split into multiple
+ * independent providers.
+ *
+ * When the Bluetooth stack is ready to create an audio session, it must first
+ * obtain the IBluetoothAudioProvider for that session type by calling
+ * openProvider().
+ *
+ */
+
+@VintfStability
+interface IBluetoothAudioProviderFactory {
+    /**
+     * Gets a list of audio capabilities for a session type.
+     *
+     * For software encoding, the PCM capabilities are returned.
+     * For hardware encoding, the supported codecs and their capabilities are
+     * returned.
+     *
+     * @param sessionType The session type (e.g.
+     *    A2DP_SOFTWARE_ENCODING_DATAPATH).
+     * @return A list containing all the capabilities
+     *    supported by the sesson type. The capabilities is a list of
+     *    available options when configuring the codec for the session.
+     *    For software encoding it is the PCM data rate.
+     *    For hardware encoding it is the list of supported codecs and their
+     *    capabilities.
+     *    If a provider isn't supported, an empty list should be returned.
+     *    Note: Only one entry should exist per codec when using hardware
+     *    encoding.
+     */
+    AudioCapabilities[] getProviderCapabilities(in SessionType sessionType);
+
+    /**
+     * Opens an audio provider for a session type. To close the provider, it is
+     * necessary to release references to the returned provider object.
+     *
+     * @param sessionType The session type (e.g.
+     *    LE_AUDIO_SOFTWARE_ENCODING_DATAPATH).
+     *
+     * @return provider The provider of the specified session type
+     */
+    IBluetoothAudioProvider openProvider(in SessionType sessionType);
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
new file mode 100644
index 0000000..1aedefd
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+/**
+ * Used for Hardware Encoding/Decoding LC3 codec capabilities.
+ */
+@VintfStability
+parcelable Lc3Capabilities {
+    /*
+     * PCM is Input for encoder, Output for decoder
+     */
+    byte[] pcmBitDepth;
+    /*
+     * codec-specific parameters
+     */
+    int[] samplingFrequencyHz;
+    /*
+     * FrameDuration based on microseconds.
+     */
+    int[] frameDurationUs;
+    /*
+     * length in octets of a codec frame
+     */
+    int[] octetsPerFrame;
+    /*
+     * Number of blocks of codec frames per single SDU (Service Data Unit)
+     */
+    byte[] blocksPerSdu;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl
new file mode 100644
index 0000000..77c04c1
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+/**
+ * Used for Hardware Encoding/Decoding LC3 codec configuration.
+ */
+@VintfStability
+parcelable Lc3Configuration {
+    /*
+     * PCM is Input for encoder, Output for decoder
+     */
+    byte pcmBitDepth;
+    /*
+     * codec-specific parameters
+     */
+    int samplingFrequencyHz;
+    /*
+     * FrameDuration based on microseconds.
+     */
+    int frameDurationUs;
+    /*
+     * length in octets of a codec frame
+     */
+    int octetsPerFrame;
+    /*
+     * Number of blocks of codec frames per single SDU (Service Data Unit)
+     */
+    byte blocksPerSdu;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl
new file mode 100644
index 0000000..44cca7e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.LdacChannelMode;
+import android.hardware.bluetooth.audio.LdacQualityIndex;
+
+/**
+ * Used for Hardware Encoding LDAC codec capabilities
+ * all qualities must be supported.
+ */
+@VintfStability
+parcelable LdacCapabilities {
+    int[] sampleRateHz;
+    /* bitfiled */
+    LdacChannelMode channelMode;
+    /* bitfiled */
+    LdacQualityIndex qualityIndex;
+    byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl
new file mode 100644
index 0000000..3acca32
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+/**
+ * Channel Mode: 3 bits
+ */
+@VintfStability
+@Backing(type="byte")
+enum LdacChannelMode {
+    UNKNOWN = 1,
+    STEREO = 1 << 1,
+    DUAL = 1 << 2,
+    MONO = 1 << 3,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacConfiguration.aidl
new file mode 100644
index 0000000..cc03dd0
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacConfiguration.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.LdacChannelMode;
+import android.hardware.bluetooth.audio.LdacQualityIndex;
+
+/**
+ * Used for Hardware Encoding LDAC codec configuration
+ * Only used when configuring the codec.
+ */
+@VintfStability
+parcelable LdacConfiguration {
+    int sampleRateHz;
+    LdacChannelMode channelMode;
+    LdacQualityIndex qualityIndex;
+    byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
new file mode 100644
index 0000000..cb12583
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum LdacQualityIndex {
+    /**
+     * 990kbps
+     */
+    HIGH = 1,
+    /**
+     * 660kbps
+     */
+    MID = 1 << 1,
+    /**
+     * 330kbps
+     */
+    LOW = 1 << 2,
+    /**
+     * Adaptive Bit Rate mode
+     */
+    ABR = 1 << 3,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCapabilities.aidl
new file mode 100644
index 0000000..732427f
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCapabilities.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AudioLocation;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.Lc3Capabilities;
+import android.hardware.bluetooth.audio.LeAudioMode;
+
+/**
+ * Used to specify the capabilities of the LC3 codecs supported by Hardware Encoding.
+ */
+@VintfStability
+parcelable LeAudioCapabilities {
+    @VintfStability
+    parcelable VendorCapabilities {
+        ParcelableHolder extension;
+    }
+    @VintfStability
+    union LeAudioCodecCapabilities {
+        Lc3Capabilities lc3Capabilities;
+        VendorCapabilities vendorCapabillities;
+    }
+    LeAudioMode mode;
+    CodecType codecType;
+    /*
+     * This is bitfield, if bit N is set, HW Offloader supports N+1 channels at the same time.
+     * Example: 0x27 = 0b00100111: One, two, three or six channels supported.
+     */
+    AudioLocation supportedChannel;
+    int supportedChannelCount;
+    LeAudioCodecCapabilities leAudioCodecCapabilities;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
new file mode 100644
index 0000000..421eeb2
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.Lc3Configuration;
+
+@VintfStability
+union LeAudioCodecConfiguration {
+    @VintfStability
+    parcelable VendorConfiguration {
+        ParcelableHolder extension;
+    }
+    Lc3Configuration lc3Config;
+    VendorConfiguration vendorConfig;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
new file mode 100644
index 0000000..515794b
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.BroadcastConfiguration;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.LeAudioMode;
+import android.hardware.bluetooth.audio.UnicastConfiguration;
+
+@VintfStability
+parcelable LeAudioConfiguration {
+    @VintfStability
+    union LeAudioModeConfig {
+        UnicastConfiguration unicastConfig;
+        BroadcastConfiguration broadcastConfig;
+    }
+    /*
+     * The mode of the LE audio
+     */
+    LeAudioMode mode;
+    LeAudioModeConfig modeConfig;
+    CodecType codecType;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioMode.aidl
new file mode 100644
index 0000000..2cf019e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioMode.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum LeAudioMode {
+    UNKNOWN,
+    UNICAST,
+    BROADCAST,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl
new file mode 100644
index 0000000..f5d699e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Software Encoding audio feed capabilities
+ */
+@VintfStability
+parcelable PcmCapabilities {
+    int[] sampleRateHz;
+    ChannelMode channelMode;
+    byte[] bitsPerSample;
+    /**
+     * Data interval for data transfer
+     */
+    int[] dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmConfiguration.aidl
new file mode 100644
index 0000000..03aa27b
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmConfiguration.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Software Encoding audio feed configuration
+ */
+@VintfStability
+parcelable PcmConfiguration {
+    int sampleRateHz;
+    ChannelMode channelMode;
+    byte bitsPerSample;
+    /**
+     * Data interval for data transfer
+     */
+    int dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PresentationPosition.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PresentationPosition.aidl
new file mode 100644
index 0000000..f3b8aed
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PresentationPosition.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+parcelable PresentationPosition {
+    @VintfStability
+    parcelable TimeSpec {
+        /**
+         * seconds
+         */
+        long tvSec;
+        /**
+         *  nanoseconds
+         */
+        long tvNSec;
+    }
+    /*
+     * remoteDeviceAudioDelayNanos the audio delay from when the remote
+     * device (e.g. headset) receives audio data to when the device plays the
+     * sound. If the delay is unknown, the value is set to zero.
+     */
+    long remoteDeviceAudioDelayNanos;
+    /*
+     * transmittedOctets the number of audio data octets that were sent
+     * to a remote device. This excludes octets that have been written to the
+     * data path but have not been sent to the remote device. The count is
+     * not reset until stopStream() is called. If the software data path is
+     * unused (e.g. Hardware Offload), the value is set to 0.
+     */
+    long transmittedOctets;
+    /*
+     * transmittedOctetsTimestamp the value of CLOCK_MONOTONIC
+     * corresponding to transmittedOctets. If the software data path is
+     * unused (e.g., for Hardware Offload), the value is set to zero.
+     */
+    TimeSpec transmittedOctetsTimestamp;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
new file mode 100644
index 0000000..7047e34
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum SbcAllocMethod {
+    /**
+     * SNR
+     */
+    ALLOC_MD_S = 1,
+    /**
+     * Loudness
+     */
+    ALLOC_MD_L = 1 << 1,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl
new file mode 100644
index 0000000..cf62ed4
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.SbcAllocMethod;
+import android.hardware.bluetooth.audio.SbcChannelMode;
+
+/**
+ * Used for Hardware Encoding SBC codec capabilities.
+ */
+@VintfStability
+parcelable SbcCapabilities {
+    int[] sampleRateHz;
+    /* bitfield */
+    SbcChannelMode channelMode;
+    byte[] blockLength;
+    byte[] numSubbands;
+    /* bitfield */
+    SbcAllocMethod allocMethod;
+    byte[] bitsPerSample;
+    /*
+     * range from 2 to 250.
+     */
+    int minBitpool;
+    /*
+     * range from 2 to 250.
+     */
+    int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl
new file mode 100644
index 0000000..7eb38cd
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum SbcChannelMode {
+    UNKNOWN = 1,
+    JOINT_STEREO = 1 << 1,
+    STEREO = 1 << 2,
+    DUAL = 1 << 3,
+    MONO = 1 << 4,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcConfiguration.aidl
new file mode 100644
index 0000000..054d03e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.SbcAllocMethod;
+import android.hardware.bluetooth.audio.SbcChannelMode;
+
+/**
+ * Used for Hardware Encoding SBC codec configuration.
+ */
+@VintfStability
+parcelable SbcConfiguration {
+    int sampleRateHz;
+    SbcChannelMode channelMode;
+    byte blockLength;
+    byte numSubbands;
+    SbcAllocMethod allocMethod;
+    byte bitsPerSample;
+    /*
+     * range from 2 to 250.
+     */
+    int minBitpool;
+    /*
+     * range from 2 to 250.
+     */
+    int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl
new file mode 100644
index 0000000..30faae3
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum SessionType {
+    UNKNOWN,
+    /**
+     * A2DP legacy that AVDTP media is encoded by Bluetooth Stack
+     */
+    A2DP_SOFTWARE_ENCODING_DATAPATH,
+    /**
+     * The encoding of AVDTP media is done by HW and there is control only
+     */
+    A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+    /**
+     * Used when encoded by Bluetooth Stack and streaming to Hearing Aid
+     */
+    HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+    /**
+     * Used when encoded by Bluetooth Stack and streaming to LE Audio device
+     */
+    LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
+    /**
+     * Used when decoded by Bluetooth Stack and streaming to audio framework
+     */
+    LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
+    /**
+     * Encoding is done by HW an there is control only
+     */
+    LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+    /**
+     * Decoding is done by HW an there is control only
+     */
+    LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastConfiguration.aidl
new file mode 100644
index 0000000..7be2c5b
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.LeAudioCodecConfiguration;
+
+@VintfStability
+parcelable UnicastConfiguration {
+    @VintfStability
+    parcelable UnicastStreamMap {
+        /*
+         * The connection handle used for a unicast or a broadcast group.
+         * Range: 0x0000 to 0xEFFF
+         */
+        char streamHandle;
+        /*
+         * Audio channel allocation is  a bit field, each enabled bit means that given audio
+         * direction, i.e. "left", or "right" is used. Ordering of audio channels comes from the
+         * least significant bit to the most significant bit. The valus follows the Bluetooth SIG
+         * Audio Location assigned number.
+         */
+        int audioChannelAllocation;
+    }
+    UnicastStreamMap[] streamMap;
+    int peerDelay;
+    LeAudioCodecConfiguration leAudioCodecConfig;
+}
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index 677b496..311c688 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -413,8 +413,8 @@
     const uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
     UPDATE(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
 
-    const int32_t testPatternModes[] = {
-        ANDROID_SENSOR_TEST_PATTERN_MODE_OFF};
+    const int32_t testPatternModes[] = {ANDROID_SENSOR_TEST_PATTERN_MODE_OFF,
+                                        ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR};
     UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes,
            ARRAY_SIZE(testPatternModes));
 
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 5f86742..ca7186b 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -1462,14 +1462,50 @@
         return onDeviceError("%s: V4L2 buffer map failed", __FUNCTION__);
     }
 
+    // Process camera mute state
+    auto testPatternMode = req->setting.find(ANDROID_SENSOR_TEST_PATTERN_MODE);
+    if (testPatternMode.count == 1) {
+        if (mCameraMuted != (testPatternMode.data.u8[0] != ANDROID_SENSOR_TEST_PATTERN_MODE_OFF)) {
+            mCameraMuted = !mCameraMuted;
+            // Get solid color for test pattern, if any was set
+            if (testPatternMode.data.u8[0] == ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR) {
+                auto entry = req->setting.find(ANDROID_SENSOR_TEST_PATTERN_DATA);
+                if (entry.count == 4) {
+                    // Update the mute frame if the pattern color has changed
+                    if (memcmp(entry.data.i32, mTestPatternData, sizeof(mTestPatternData)) != 0) {
+                        memcpy(mTestPatternData, entry.data.i32, sizeof(mTestPatternData));
+                        // Fill the mute frame with the solid color, use only 8 MSB of RGGB as RGB
+                        for (int i = 0; i < mMuteTestPatternFrame.size(); i += 3) {
+                            mMuteTestPatternFrame[i] = entry.data.i32[0] >> 24;
+                            mMuteTestPatternFrame[i + 1] = entry.data.i32[1] >> 24;
+                            mMuteTestPatternFrame[i + 2] = entry.data.i32[3] >> 24;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     // TODO: in some special case maybe we can decode jpg directly to gralloc output?
     if (req->frameIn->mFourcc == V4L2_PIX_FMT_MJPEG) {
         ATRACE_BEGIN("MJPGtoI420");
-        int res = libyuv::MJPGToI420(
-            inData, inDataSize, static_cast<uint8_t*>(mYu12FrameLayout.y), mYu12FrameLayout.yStride,
-            static_cast<uint8_t*>(mYu12FrameLayout.cb), mYu12FrameLayout.cStride,
-            static_cast<uint8_t*>(mYu12FrameLayout.cr), mYu12FrameLayout.cStride,
-            mYu12Frame->mWidth, mYu12Frame->mHeight, mYu12Frame->mWidth, mYu12Frame->mHeight);
+        int res = 0;
+        if (mCameraMuted) {
+            res = libyuv::ConvertToI420(
+                    mMuteTestPatternFrame.data(), mMuteTestPatternFrame.size(),
+                    static_cast<uint8_t*>(mYu12FrameLayout.y), mYu12FrameLayout.yStride,
+                    static_cast<uint8_t*>(mYu12FrameLayout.cb), mYu12FrameLayout.cStride,
+                    static_cast<uint8_t*>(mYu12FrameLayout.cr), mYu12FrameLayout.cStride, 0, 0,
+                    mYu12Frame->mWidth, mYu12Frame->mHeight, mYu12Frame->mWidth,
+                    mYu12Frame->mHeight, libyuv::kRotate0, libyuv::FOURCC_RAW);
+        } else {
+            res = libyuv::MJPGToI420(
+                    inData, inDataSize, static_cast<uint8_t*>(mYu12FrameLayout.y),
+                    mYu12FrameLayout.yStride, static_cast<uint8_t*>(mYu12FrameLayout.cb),
+                    mYu12FrameLayout.cStride, static_cast<uint8_t*>(mYu12FrameLayout.cr),
+                    mYu12FrameLayout.cStride, mYu12Frame->mWidth, mYu12Frame->mHeight,
+                    mYu12Frame->mWidth, mYu12Frame->mHeight);
+        }
         ATRACE_END();
 
         if (res != 0) {
@@ -1670,6 +1706,9 @@
         }
     }
 
+    // Allocate mute test pattern frame
+    mMuteTestPatternFrame.resize(mYu12Frame->mWidth * mYu12Frame->mHeight * 3);
+
     mBlobBufferSize = blobBufferSize;
     return Status::OK;
 }
@@ -1679,6 +1718,7 @@
     mYu12Frame.clear();
     mYu12ThumbFrame.clear();
     mIntermediateBuffers.clear();
+    mMuteTestPatternFrame.clear();
     mBlobBufferSize = 0;
 }
 
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
index 180f0c1..184c16e 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
@@ -181,6 +181,9 @@
         std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mScaledYu12Frames;
         YCbCrLayout mYu12FrameLayout;
         YCbCrLayout mYu12ThumbFrameLayout;
+        std::vector<uint8_t> mMuteTestPatternFrame;
+        uint32_t mTestPatternData[4] = {0, 0, 0, 0};
+        bool mCameraMuted = false;
         uint32_t mBlobBufferSize = 0; // 0 -> HAL derive buffer size, else: use given size
 
         std::string mExifMake;
diff --git a/camera/device/3.8/Android.bp b/camera/device/3.8/Android.bp
new file mode 100644
index 0000000..2a1f215
--- /dev/null
+++ b/camera/device/3.8/Android.bp
@@ -0,0 +1,38 @@
+// 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.camera.device@3.8",
+    root: "android.hardware",
+    srcs: [
+        "types.hal",
+        "ICameraDevice.hal",
+        "ICameraDeviceCallback.hal",
+    ],
+    interfaces: [
+        "android.hardware.camera.common@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.device@3.7",
+        "android.hardware.camera.metadata@3.2",
+        "android.hardware.camera.metadata@3.3",
+        "android.hardware.camera.metadata@3.4",
+        "android.hardware.camera.metadata@3.5",
+        "android.hardware.camera.metadata@3.6",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: false,
+}
diff --git a/camera/device/3.8/ICameraDevice.hal b/camera/device/3.8/ICameraDevice.hal
new file mode 100644
index 0000000..1101819
--- /dev/null
+++ b/camera/device/3.8/ICameraDevice.hal
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera.device@3.8;
+
+import android.hardware.camera.common@1.0::Status;
+import @3.7::ICameraDevice;
+
+/**
+ * Camera device interface
+ *
+ * Supports the android.hardware.Camera API, and the android.hardware.camera2
+ * API at LIMITED or better hardware level.
+ *
+ * ICameraDevice.open() must return @3.2::ICameraDeviceSession,
+ * @3.5::ICameraDeviceSession, @3.6::ICameraDeviceSession, or
+ * @3.7::ICameraDeviceSession.
+ */
+interface ICameraDevice extends @3.7::ICameraDevice {
+    /**
+     * turnOnTorchWithStrengthLevel:
+     *
+     * Change the brightness level of the flash unit associated with this camera device
+     * and set it to value in torchStrength. This function also turns ON the torch
+     * with specified torchStrength if the torch is OFF.
+     *
+     * The torchStrength value must be within the valid range i.e. >=1 and
+     * <= FLASH_INFO_STRENGTH_MAXIMUM_LEVEL. Whenever the torch is turned OFF,
+     * the brightness level will reset to FLASH_INFO_STRENGTH_DEFAULT_LEVEL.
+     * When the client calls setTorchMode(ON) after turnOnTorchWithStrengthLevel(N),
+     * the flash unit will have brightness level equal to N. This level does not
+     * represent the real brightness units. It is linear in nature i.e. flashlight
+     * at level 10 is twice as bright as at level 5.
+     *
+     * @param torchStrength Brightness level to be set for the flashlight.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful change to the torch strength level.
+     *     INTERNAL_ERROR:
+     *         The flash unit cannot be operated due to an unexpected internal
+     *         error.
+     *     CAMERA_IN_USE:
+     *         This status code is returned when:
+     *           - This camera device has been opened, so the torch cannot be
+     *             controlled until it is closed.
+     *           - Due to other camera devices being open, or due to other
+     *             resource constraints, the torch cannot be controlled currently.
+     *     ILLEGAL_ARGUMENT:
+     *         If the torchStrength value is not within the range i.e. < 1 or
+     *         > FLASH_INFO_STRENGTH_MAXIMUM_LEVEL.
+     *     METHOD_NOT_SUPPORTED:
+     *         This status code is returned when:
+     *           - This camera device does not support direct operation of flashlight
+     *             torch mode. The framework must open the camera device and turn
+     *             the torch on through the device interface.
+     *           - This camera device does not have a flash unit.
+     *           - This camera device has flash unit but does not support torch
+     *             strength control.
+     *     CAMERA_DISCONNECTED:
+     *         An external camera device has been disconnected, and is no longer
+     *         available. This camera device interface is now stale, and a new
+     *         instance must be acquired if the device is reconnected. All
+     *         subsequent calls on this interface must return
+     *         CAMERA_DISCONNECTED.
+     *
+     */
+    turnOnTorchWithStrengthLevel(int32_t torchStrength) generates (Status status);
+
+    /**
+     * getTorchStrengthLevel:
+     *
+     * Get current torch strength level.
+     * If the device supports torch strength control, when the torch is OFF the
+     * strength level will reset to default level, so the return
+     * value in this case will be equal to FLASH_INFO_STRENGTH_DEFAULT_LEVEL.
+     *
+     * @return status Status code for the operation, one of:
+     *      OK:
+     *           On success.
+     *      INTERNAL_ERROR:
+     *           An unexpected error occurred and the information is not
+     *           available.
+     *      METHOD_NOT_SUPPORTED:
+     *          This status code is returned when:
+     *            - This camera device does not support direct operation of flashlight
+     *              torch mode. The framework must open the camera device and turn
+     *              the torch on through the device interface.
+     *            - This camera device does not have a flash unit.
+     *            - This camera device has flash unit but does not support torch
+     *              strength control.
+     *
+     * @return torchStrength Current torch strength level.
+     *
+     */
+    getTorchStrengthLevel() generates (Status status, int32_t torchStrength);
+};
diff --git a/camera/device/3.8/ICameraDeviceCallback.hal b/camera/device/3.8/ICameraDeviceCallback.hal
new file mode 100644
index 0000000..de0775d
--- /dev/null
+++ b/camera/device/3.8/ICameraDeviceCallback.hal
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera.device@3.8;
+
+import @3.5::ICameraDeviceCallback;
+
+/**
+ * Callback methods for the HAL to call into the framework.
+ */
+interface ICameraDeviceCallback extends @3.5::ICameraDeviceCallback {
+    /**
+     * Identical to @3.5::ICameraDeviceCallback.notify, except that it takes a
+     * list of @3.8::NotifyMsg which contain readout timestamp in addition
+     * to exposure start timestamp for shutter.
+     *
+     * The readout timestamp is used for the framework to re-time the viewfinder
+     * frames targeted for SurfaceView so that preview jitter can be reduced.
+     */
+    notify_3_8(vec<NotifyMsg> msgs);
+};
diff --git a/camera/device/3.8/types.hal b/camera/device/3.8/types.hal
new file mode 100644
index 0000000..843d050
--- /dev/null
+++ b/camera/device/3.8/types.hal
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera.device@3.8;
+
+import @3.2::ErrorMsg;
+import @3.2::MsgType;
+import @3.2::ShutterMsg;
+
+/**
+ * ShutterMsg:
+ *
+ * Message contents for MsgType::SHUTTER
+ *
+ * This version extends the @3.2 ShutterMsg with the readout timestamp.
+ */
+struct ShutterMsg {
+    /**
+     * The definition of ShutterMsg from prior version.
+     */
+    @3.2::ShutterMsg v3_2;
+
+    /**
+     * Timestamp for the capture readout. This must be in the same time domain
+     * as v3_2.timestamp, and for a rolling shutter sensor, the value must be
+     * v3_2.timestamp + exposureTime + t_crop_top where t_crop_top is the exposure time
+     * skew of the cropped lines on the top.
+     */
+    uint64_t readoutTimestamp;
+};
+
+/**
+ * NotifyMsg:
+ *
+ * The message structure sent to ICameraDevice3Callback::notify()
+ *
+ * This version extends the @3.2 NotifyMsg with the @3.8 version of ShutterMsg.
+ */
+struct NotifyMsg {
+    /**
+     * The message type.
+     */
+    @3.2::MsgType type;
+
+    union Message {
+        /**
+         * Error message contents. Valid if type is MsgType::ERROR
+         */
+        @3.2::ErrorMsg error;
+
+        /**
+         * Shutter message contents. Valid if type is MsgType::SHUTTER
+         */
+        ShutterMsg shutter;
+    } msg;
+};
diff --git a/camera/metadata/3.7/Android.bp b/camera/metadata/3.7/Android.bp
new file mode 100644
index 0000000..14981b8
--- /dev/null
+++ b/camera/metadata/3.7/Android.bp
@@ -0,0 +1,26 @@
+// 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.camera.metadata@3.7",
+    root: "android.hardware",
+    srcs: [
+        "types.hal",
+    ],
+    interfaces: [
+        "android.hardware.camera.metadata@3.2",
+        "android.hardware.camera.metadata@3.3",
+        "android.hardware.camera.metadata@3.4",
+        "android.hardware.camera.metadata@3.5",
+        "android.hardware.camera.metadata@3.6",
+    ],
+    gen_java: true,
+}
diff --git a/camera/metadata/3.8/Android.bp b/camera/metadata/3.8/Android.bp
new file mode 100644
index 0000000..ead9543
--- /dev/null
+++ b/camera/metadata/3.8/Android.bp
@@ -0,0 +1,27 @@
+// 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.camera.metadata@3.8",
+    root: "android.hardware",
+    srcs: [
+        "types.hal",
+    ],
+    interfaces: [
+        "android.hardware.camera.metadata@3.2",
+        "android.hardware.camera.metadata@3.3",
+        "android.hardware.camera.metadata@3.4",
+        "android.hardware.camera.metadata@3.5",
+        "android.hardware.camera.metadata@3.6",
+        "android.hardware.camera.metadata@3.7",
+    ],
+    gen_java: true,
+}
diff --git a/camera/metadata/3.8/types.hal b/camera/metadata/3.8/types.hal
new file mode 100644
index 0000000..11360da
--- /dev/null
+++ b/camera/metadata/3.8/types.hal
@@ -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.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata@3.8;
+
+import android.hardware.camera.metadata@3.2;
+import android.hardware.camera.metadata@3.3;
+import android.hardware.camera.metadata@3.4;
+import android.hardware.camera.metadata@3.5;
+import android.hardware.camera.metadata@3.6;
+import android.hardware.camera.metadata@3.7;
+
+// No new metadata sections added in this revision
+
+/**
+ * Main enumeration for defining camera metadata tags added in this revision
+ *
+ * <p>Partial documentation is included for each tag; for complete documentation, reference
+ * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
+ */
+enum CameraMetadataTag : @3.7::CameraMetadataTag {
+    /** android.flash.info.strengthMaximumLevel [static, int32, public]
+     *
+     * <p>Maximum flashlight brightness level.</p>
+     */
+    ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_FLASH_INFO_END,
+
+    /** android.flash.info.strengthDefaultLevel [static, int32, public]
+     *
+     * <p>Default flashlight brightness level to be set via
+     * {android.hardware.camera2.CameraManager#turnOnTorchWithStrengthLevel}.</p>
+     */
+    ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL,
+
+    ANDROID_FLASH_INFO_END_3_8,
+
+};
+
+/*
+ * Enumeration definitions for the various entries that need them
+ */
+
+/** android.control.videoStabilizationMode enumeration values added since v3.2
+ * @see ANDROID_CONTROL_VIDEO_STABILIZATION_MODE
+ */
+enum CameraMetadataEnumAndroidControlVideoStabilizationMode :
+        @3.2::CameraMetadataEnumAndroidControlVideoStabilizationMode {
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION,
+};
diff --git a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
index 64a51f6..4fc7437 100644
--- a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
+++ b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
@@ -65,10 +65,10 @@
 
 } // anonymous namespace
 
-ExternalCameraProviderImpl_2_4::ExternalCameraProviderImpl_2_4() :
-        mCfg(ExternalCameraConfig::loadFromCfg()),
-        mHotPlugThread(this) {
-    mHotPlugThread.run("ExtCamHotPlug", PRIORITY_BACKGROUND);
+ExternalCameraProviderImpl_2_4::ExternalCameraProviderImpl_2_4()
+    : mCfg(ExternalCameraConfig::loadFromCfg()) {
+    mHotPlugThread = sp<HotplugThread>::make(this);
+    mHotPlugThread->run("ExtCamHotPlug", PRIORITY_BACKGROUND);
 
     mPreferredHal3MinorVersion =
         property_get_int32("ro.vendor.camera.external.hal3TrebleMinorVersion", 4);
@@ -88,7 +88,7 @@
 }
 
 ExternalCameraProviderImpl_2_4::~ExternalCameraProviderImpl_2_4() {
-    mHotPlugThread.requestExit();
+    mHotPlugThread->requestExit();
 }
 
 
diff --git a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.h b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.h
index 8c79f68..f1d8003 100644
--- a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.h
+++ b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.h
@@ -102,7 +102,7 @@
     sp<ICameraProviderCallback> mCallbacks = nullptr;
     std::unordered_map<std::string, CameraDeviceStatus> mCameraStatusMap; // camera id -> status
     const ExternalCameraConfig mCfg;
-    HotplugThread mHotPlugThread;
+    sp<HotplugThread> mHotPlugThread;
     int mPreferredHal3MinorVersion;
 };
 
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 8886ee1..2c141ee 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -49,6 +49,7 @@
         "android.hardware.camera.device@3.5",
         "android.hardware.camera.device@3.6",
         "android.hardware.camera.device@3.7",
+        "android.hardware.camera.device@3.8",
         "android.hardware.camera.metadata@3.4",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.provider@2.5",
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index d02547c..d39850d 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -41,8 +41,10 @@
 #include <android/hardware/camera/device/3.6/ICameraDevice.h>
 #include <android/hardware/camera/device/3.6/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.7/ICameraDevice.h>
+#include <android/hardware/camera/device/3.8/ICameraDevice.h>
 #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/metadata/3.4/types.h>
 #include <android/hardware/camera/provider/2.4/ICameraProvider.h>
 #include <android/hardware/camera/provider/2.5/ICameraProvider.h>
@@ -194,6 +196,7 @@
 namespace {
     // "device@<version>/legacy/<id>"
     const char *kDeviceNameRE = "device@([0-9]+\\.[0-9]+)/%s/(.+)";
+    const int CAMERA_DEVICE_API_VERSION_3_8 = 0x308;
     const int CAMERA_DEVICE_API_VERSION_3_7 = 0x307;
     const int CAMERA_DEVICE_API_VERSION_3_6 = 0x306;
     const int CAMERA_DEVICE_API_VERSION_3_5 = 0x305;
@@ -201,6 +204,7 @@
     const int CAMERA_DEVICE_API_VERSION_3_3 = 0x303;
     const int CAMERA_DEVICE_API_VERSION_3_2 = 0x302;
     const int CAMERA_DEVICE_API_VERSION_1_0 = 0x100;
+    const char *kHAL3_8 = "3.8";
     const char *kHAL3_7 = "3.7";
     const char *kHAL3_6 = "3.6";
     const char *kHAL3_5 = "3.5";
@@ -238,7 +242,9 @@
             return -1;
         }
 
-        if (version.compare(kHAL3_7) == 0) {
+        if (version.compare(kHAL3_8) == 0) {
+            return CAMERA_DEVICE_API_VERSION_3_8;
+        } else if (version.compare(kHAL3_7) == 0) {
             return CAMERA_DEVICE_API_VERSION_3_7;
         } else if (version.compare(kHAL3_6) == 0) {
             return CAMERA_DEVICE_API_VERSION_3_6;
@@ -638,7 +644,7 @@
      }
  };
 
-    struct DeviceCb : public V3_5::ICameraDeviceCallback {
+    struct DeviceCb : public V3_8::ICameraDeviceCallback {
         DeviceCb(CameraHidlTest *parent, int deviceVersion, const camera_metadata_t *staticMeta) :
                 mParent(parent), mDeviceVersion(deviceVersion) {
             mStaticMetadata = staticMeta;
@@ -648,6 +654,7 @@
                 const hidl_vec<V3_4::CaptureResult>& results) override;
         Return<void> processCaptureResult(const hidl_vec<CaptureResult>& results) override;
         Return<void> notify(const hidl_vec<NotifyMsg>& msgs) override;
+        Return<void> notify_3_8(const hidl_vec<V3_8::NotifyMsg>& msgs) override;
 
         Return<void> requestStreamBuffers(
                 const hidl_vec<V3_5::BufferRequest>& bufReqs,
@@ -660,9 +667,11 @@
 
         void waitForBuffersReturned();
 
-     private:
+      private:
         bool processCaptureResultLocked(const CaptureResult& results,
                 hidl_vec<PhysicalCameraMetadata> physicalCameraMetadata);
+        Return<void> notifyHelper(const hidl_vec<NotifyMsg>& msgs,
+                const std::vector<std::pair<bool, nsecs_t>>& readoutTimestamps);
 
         CameraHidlTest *mParent; // Parent object
         int mDeviceVersion;
@@ -898,11 +907,12 @@
 
     static Status getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
                                                 std::vector<AvailableStream>* outputStreams);
-
+    static bool supportsPreviewStabilization(const std::string& name, sp<ICameraProvider> provider);
     static Status getJpegBufferSize(camera_metadata_t *staticMeta,
             uint32_t* outBufSize);
     static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
     static Status isLogicalMultiCamera(const camera_metadata_t *staticMeta);
+    static bool isTorchStrengthControlSupported(const camera_metadata_t *staticMeta);
     static Status isOfflineSessionSupported(const camera_metadata_t *staticMeta);
     static Status getPhysicalCameraIds(const camera_metadata_t *staticMeta,
             std::unordered_set<std::string> *physicalIds/*out*/);
@@ -945,6 +955,9 @@
 
     void processCaptureRequestInternal(uint64_t bufferusage, RequestTemplate reqTemplate,
                                        bool useSecureOnlyCameras);
+    void processPreviewStabilizationCaptureRequestInternal(
+            bool previewStabilizationOn,
+            /*inout*/ std::unordered_map<std::string, nsecs_t>& cameraDeviceToTimeLag);
 
     // Used by switchToOffline where a new result queue is created for offline reqs
     void updateInflightResultQueue(std::shared_ptr<ResultMetadataQueue> resultQueue);
@@ -956,6 +969,9 @@
         // Set by notify() SHUTTER call.
         nsecs_t shutterTimestamp;
 
+        bool shutterReadoutTimestampValid;
+        nsecs_t shutterReadoutTimestamp;
+
         bool errorCodeValid;
         ErrorCode errorCode;
 
@@ -995,12 +1011,18 @@
 
         // Buffers are added by process_capture_result when output buffers
         // return from HAL but framework.
-        ::android::Vector<StreamBuffer> resultOutputBuffers;
+        struct StreamBufferAndTimestamp {
+            StreamBuffer buffer;
+            nsecs_t timeStamp;
+        };
+        ::android::Vector<StreamBufferAndTimestamp> resultOutputBuffers;
 
         std::unordered_set<std::string> expectedPhysicalResults;
 
         InFlightRequest() :
                 shutterTimestamp(0),
+                shutterReadoutTimestampValid(false),
+                shutterReadoutTimestamp(0),
                 errorCodeValid(false),
                 errorCode(ErrorCode::ERROR_BUFFER),
                 usePartialResult(false),
@@ -1018,6 +1040,8 @@
                 bool partialResults, uint32_t partialCount,
                 std::shared_ptr<ResultMetadataQueue> queue = nullptr) :
                 shutterTimestamp(0),
+                shutterReadoutTimestampValid(false),
+                shutterReadoutTimestamp(0),
                 errorCodeValid(false),
                 errorCode(ErrorCode::ERROR_BUFFER),
                 usePartialResult(partialResults),
@@ -1036,6 +1060,8 @@
                 const std::unordered_set<std::string>& extraPhysicalResult,
                 std::shared_ptr<ResultMetadataQueue> queue = nullptr) :
                 shutterTimestamp(0),
+                shutterReadoutTimestampValid(false),
+                shutterReadoutTimestamp(0),
                 errorCodeValid(false),
                 errorCode(ErrorCode::ERROR_BUFFER),
                 usePartialResult(partialResults),
@@ -1404,8 +1430,25 @@
         return notify;
     }
 
-    request->resultOutputBuffers.appendArray(results.outputBuffers.data(),
-            results.outputBuffers.size());
+    for (const auto& buffer : results.outputBuffers) {
+        // wait for the fence timestamp and store it along with the buffer
+        // TODO: Check if we really need the dup here
+        sp<android::Fence> releaseFence = nullptr;
+        if (buffer.releaseFence && (buffer.releaseFence->numFds == 1) &&
+            buffer.releaseFence->data[0] >= 0) {
+            releaseFence = new android::Fence(dup(buffer.releaseFence->data[0]));
+        }
+        InFlightRequest::StreamBufferAndTimestamp streamBufferAndTimestamp;
+        streamBufferAndTimestamp.buffer = buffer;
+        streamBufferAndTimestamp.timeStamp = systemTime();
+        if (releaseFence && releaseFence->isValid()) {
+            releaseFence->wait(/*ms*/ 300);
+            nsecs_t releaseTime = releaseFence->getSignalTime();
+            if (streamBufferAndTimestamp.timeStamp < releaseTime)
+                streamBufferAndTimestamp.timeStamp = releaseTime;
+        }
+        request->resultOutputBuffers.push_back(streamBufferAndTimestamp);
+    }
     // If shutter event is received notify the pending threads.
     if (request->shutterTimestamp != 0) {
         notify = true;
@@ -1462,8 +1505,46 @@
     }
 }
 
+Return<void> CameraHidlTest::DeviceCb::notify_3_8(
+        const hidl_vec<V3_8::NotifyMsg>& msgs) {
+    hidl_vec<NotifyMsg> msgs3_2;
+    std::vector<std::pair<bool, nsecs_t>> readoutTimestamps;
+
+    nsecs_t count = msgs.size();
+    msgs3_2.resize(count);
+    readoutTimestamps.resize(count);
+
+    for (size_t i = 0; i < count; i++) {
+        msgs3_2[i].type = msgs[i].type;
+        switch (msgs[i].type) {
+            case MsgType::ERROR:
+                msgs3_2[i].msg.error = msgs[i].msg.error;
+                readoutTimestamps[i] = {false, 0};
+                break;
+            case MsgType::SHUTTER:
+                msgs3_2[i].msg.shutter = msgs[i].msg.shutter.v3_2;
+                readoutTimestamps[i] = {true, msgs[i].msg.shutter.readoutTimestamp};
+                break;
+        }
+    }
+
+    return notifyHelper(msgs3_2, readoutTimestamps);
+}
+
 Return<void> CameraHidlTest::DeviceCb::notify(
         const hidl_vec<NotifyMsg>& messages) {
+    std::vector<std::pair<bool, nsecs_t>> readoutTimestamps;
+    readoutTimestamps.resize(messages.size());
+    for (size_t i = 0; i < messages.size(); i++) {
+        readoutTimestamps[i] = {false, 0};
+    }
+
+    return notifyHelper(messages, readoutTimestamps);
+}
+
+Return<void> CameraHidlTest::DeviceCb::notifyHelper(
+        const hidl_vec<NotifyMsg>& messages,
+        const std::vector<std::pair<bool, nsecs_t>>& readoutTimestamps) {
     std::lock_guard<std::mutex> l(mParent->mLock);
 
     for (size_t i = 0; i < messages.size(); i++) {
@@ -1526,6 +1607,8 @@
                 }
                 InFlightRequest *r = mParent->mInflightMap.editValueAt(idx);
                 r->shutterTimestamp = messages[i].msg.shutter.timestamp;
+                r->shutterReadoutTimestampValid = readoutTimestamps[i].first;
+                r->shutterReadoutTimestamp = readoutTimestamps[i].second;
             }
                 break;
             default:
@@ -1940,6 +2023,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         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:
@@ -1984,6 +2068,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         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:
@@ -2725,6 +2810,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         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:
@@ -2812,6 +2898,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         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:
@@ -2872,6 +2959,137 @@
     }
 }
 
+// Verify that the torch strength level can be set and retrieved successfully.
+TEST_P(CameraHidlTest, turnOnTorchWithStrengthLevel) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    bool torchControlSupported = false;
+    bool torchStrengthControlSupported = false;
+    Return<void> ret;
+
+    ret = mProvider->isSetTorchModeSupported([&](auto status, bool support) {
+        ALOGI("isSetTorchModeSupported returns status:%d supported:%d", (int)status, support);
+        ASSERT_EQ(Status::OK, status);
+        torchControlSupported = support;
+    });
+
+    sp<TorchProviderCb> cb = new TorchProviderCb(this);
+    Return<Status> returnStatus = mProvider->setCallback(cb);
+    ASSERT_TRUE(returnStatus.isOk());
+    ASSERT_EQ(Status::OK, returnStatus);
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        int32_t defaultLevel;
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_8: {
+                ::android::sp<::android::hardware::camera::device::V3_8::ICameraDevice> device3_8;
+                ALOGI("%s: Testing camera device %s", __FUNCTION__, name.c_str());
+                ret = mProvider->getCameraDeviceInterface_V3_x(
+                        name, [&](auto status, const auto& device) {
+                            ASSERT_EQ(Status::OK, status);
+                            ASSERT_NE(device, nullptr);
+                            auto castResult = device::V3_8::ICameraDevice::castFrom(device);
+                            ASSERT_TRUE(castResult.isOk());
+                            device3_8 = castResult;
+                        });
+                ASSERT_TRUE(ret.isOk());
+
+                ret = device3_8->getCameraCharacteristics([&] (auto s, const auto& chars) {
+                    ASSERT_EQ(Status::OK, s);
+                    const camera_metadata_t* staticMeta =
+                            reinterpret_cast<const camera_metadata_t*>(chars.data());
+                    ASSERT_NE(nullptr, staticMeta);
+                    torchStrengthControlSupported = isTorchStrengthControlSupported(staticMeta);
+                    camera_metadata_ro_entry entry;
+                    int rc = find_camera_metadata_ro_entry(staticMeta,
+                            ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL, &entry);
+                    if (torchStrengthControlSupported) {
+                        ASSERT_EQ(rc, 0);
+                        ASSERT_GT(entry.count, 0);
+                        defaultLevel = *entry.data.i32;
+                        ALOGI("Default level is:%d", defaultLevel);
+                    }
+                });
+                ASSERT_TRUE(ret.isOk());
+                // If torchStrengthControl is supported, torchControlSupported should be true.
+                if (torchStrengthControlSupported) {
+                    ASSERT_TRUE(torchControlSupported);
+                }
+                mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
+                returnStatus = device3_8->turnOnTorchWithStrengthLevel(2);
+                ASSERT_TRUE(returnStatus.isOk());
+                // Method_not_supported check
+                if (!torchStrengthControlSupported) {
+                    ALOGI("Torch strength control not supported.");
+                    ASSERT_EQ(Status::METHOD_NOT_SUPPORTED, returnStatus);
+                } else {
+                    ASSERT_EQ(Status::OK, returnStatus);
+                    if (returnStatus == Status::OK) {
+                        {
+                            std::unique_lock<std::mutex> l(mTorchLock);
+                            while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
+                                auto timeout = std::chrono::system_clock::now() +
+                                        std::chrono::seconds(kTorchTimeoutSec);
+                                ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l,
+                                        timeout));
+                            }
+                            ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
+                            mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
+                        }
+                        ALOGI("getTorchStrengthLevel: Testing");
+                        ret = device3_8->getTorchStrengthLevel([&]
+                                (auto status, const auto& strengthLevel) {
+                                    ASSERT_TRUE(ret.isOk());
+                                    ASSERT_EQ(Status::OK, status);
+                                    ALOGI("Torch strength level is : %d", strengthLevel);
+                                    ASSERT_EQ(strengthLevel, 2);
+                                });
+                        // Turn OFF the torch and verify torch strength level is reset to default level.
+                        ALOGI("Testing torch strength level reset after turning the torch OFF.");
+                        returnStatus = device3_8->setTorchMode(TorchMode::OFF);
+                        ASSERT_TRUE(returnStatus.isOk());
+                        ASSERT_EQ(Status::OK, returnStatus);
+                        {
+                            std::unique_lock<std::mutex> l(mTorchLock);
+                            while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
+                                auto timeout = std::chrono::system_clock::now() +
+                                        std::chrono::seconds(kTorchTimeoutSec);
+                                ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l,
+                                        timeout));
+                            }
+                            ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF, mTorchStatus);
+                        }
+                        ret = device3_8->getTorchStrengthLevel([&]
+                                (auto status, const auto& strengthLevel) {
+                                    ASSERT_TRUE(ret.isOk());
+                                    ASSERT_EQ(Status::OK, status);
+                                    ALOGI("Torch strength level after turning OFF torch is : %d",
+                                            strengthLevel);
+                                    ASSERT_EQ(strengthLevel, defaultLevel);
+                                });
+                    }
+                }
+            }
+            break;
+            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:
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                ALOGI("Torch strength control feature not supported.");
+            }
+            break;
+            default: {
+                ALOGI("Invalid device version.");
+                ADD_FAILURE();
+            }
+            break;
+        }
+    }
+}
+
 //In case it is supported verify that torch can be enabled.
 //Check for corresponding toch callbacks as well.
 TEST_P(CameraHidlTest, setTorchMode) {
@@ -2893,6 +3111,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         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:
@@ -3021,6 +3240,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         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:
@@ -3088,6 +3308,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         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:
@@ -3124,7 +3345,7 @@
                 castSession(session, deviceVersion, &sessionV3_3,
                         &sessionV3_4, &sessionV3_5, &sessionV3_6,
                         &sessionV3_7);
-                if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_7) {
+                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);
@@ -3190,6 +3411,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         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:
@@ -4728,7 +4950,29 @@
 
             ASSERT_FALSE(inflightReq.errorCodeValid);
             ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-            ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].streamId);
+            ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].buffer.streamId);
+
+            // For camera device 3.8 or newer, shutterReadoutTimestamp must be
+            // available, and it must be >= shutterTimestamp + exposureTime, and
+            // < shutterTimestamp + exposureTime + rollingShutterSkew / 2.
+            if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_8) {
+                ASSERT_TRUE(inflightReq.shutterReadoutTimestampValid);
+                ASSERT_FALSE(inflightReq.collectedResult.isEmpty());
+                if (inflightReq.collectedResult.exists(ANDROID_SENSOR_EXPOSURE_TIME)) {
+                    camera_metadata_entry_t exposureTimeResult = inflightReq.collectedResult.find(
+                            ANDROID_SENSOR_EXPOSURE_TIME);
+                    nsecs_t exposureToReadout =
+                            inflightReq.shutterReadoutTimestamp - inflightReq.shutterTimestamp;
+                    ASSERT_GE(exposureToReadout, exposureTimeResult.data.i64[0]);
+                    if (inflightReq.collectedResult.exists(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW)) {
+                        camera_metadata_entry_t rollingShutterSkew =
+                                inflightReq.collectedResult.find(
+                                        ANDROID_SENSOR_ROLLING_SHUTTER_SKEW);
+                        ASSERT_LT(exposureToReadout, exposureTimeResult.data.i64[0] +
+                                                             rollingShutterSkew.data.i64[0] / 2);
+                    }
+                }
+            }
 
             request.frameNumber++;
             // Empty settings should be supported after the first call
@@ -4766,7 +5010,197 @@
 
             ASSERT_FALSE(inflightReq.errorCodeValid);
             ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-            ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].streamId);
+            ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].buffer.streamId);
+        }
+
+        if (useHalBufManager) {
+            verifyBuffersReturned(session, deviceVersion, testStream.id, cb);
+        }
+
+        ret = session->close();
+        ASSERT_TRUE(ret.isOk());
+    }
+}
+
+TEST_P(CameraHidlTest, processCaptureRequestPreviewStabilization) {
+    std::unordered_map<std::string, nsecs_t> cameraDeviceToTimeLag;
+    processPreviewStabilizationCaptureRequestInternal(/*previewStabilizationOn*/ false,
+                                                      cameraDeviceToTimeLag);
+    processPreviewStabilizationCaptureRequestInternal(/*previewStabilizationOn*/ true,
+                                                      cameraDeviceToTimeLag);
+}
+
+void CameraHidlTest::processPreviewStabilizationCaptureRequestInternal(
+        bool previewStabilizationOn,
+        // Used as output when preview stabilization is off, as output when its
+        // on.
+        std::unordered_map<std::string, nsecs_t>& cameraDeviceToTimeLag) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    AvailableStream streamThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                       static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    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_1_0) {
+            continue;
+        } else if (deviceVersion <= 0) {
+            ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+            ADD_FAILURE();
+            return;
+        }
+
+        if (!supportsPreviewStabilization(name, mProvider)) {
+            ALOGI(" %s Camera device %s doesn't support preview stabilization, skipping", __func__,
+                  name.c_str());
+            continue;
+        }
+
+        if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_8) {
+            ALOGE("%s: device version < 3.8 must not advertise preview stabilization,"
+                  " camera metadata validation will fail",
+                  __func__);
+            ADD_FAILURE();
+        }
+
+        V3_2::Stream testStream;
+        HalStreamConfiguration halStreamConfig;
+        sp<ICameraDeviceSession> session;
+        sp<DeviceCb> cb;
+        bool supportsPartialResults = false;
+        bool useHalBufManager = false;
+        uint32_t partialResultCount = 0;
+        configureSingleStream(name, deviceVersion, mProvider, &streamThreshold,
+                              GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, RequestTemplate::PREVIEW,
+                              &session /*out*/, &testStream /*out*/, &halStreamConfig /*out*/,
+                              &supportsPartialResults /*out*/, &partialResultCount /*out*/,
+                              &useHalBufManager /*out*/, &cb /*out*/);
+
+        std::shared_ptr<ResultMetadataQueue> resultQueue;
+        auto resultQueueRet =
+                session->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());
+
+        InFlightRequest inflightReq = {1, false, supportsPartialResults, partialResultCount,
+                                       resultQueue};
+
+        Return<void> ret;
+        android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
+        ret = session->constructDefaultRequestSettings(
+                RequestTemplate::PREVIEW, [&](auto status, const auto& req) {
+                    ASSERT_EQ(Status::OK, status);
+                    const camera_metadata_t* metadata =
+                            reinterpret_cast<const camera_metadata_t*>(req.data());
+                    defaultSettings = metadata;
+                    settings = req;
+                });
+        ASSERT_TRUE(ret.isOk());
+        android::status_t metadataRet = ::android::OK;
+        uint8_t videoStabilizationMode = ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
+        if (previewStabilizationOn) {
+            videoStabilizationMode = ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION;
+            metadataRet = defaultSettings.update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+                                                 &videoStabilizationMode, 1);
+        } else {
+            metadataRet = defaultSettings.update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+                                                 &videoStabilizationMode, 1);
+        }
+        ASSERT_EQ(metadataRet, ::android::OK);
+        hidl_handle buffer_handle;
+        StreamBuffer outputBuffer;
+        if (useHalBufManager) {
+            outputBuffer = {halStreamConfig.streams[0].id,
+                            /*bufferId*/ 0,
+                            buffer_handle,
+                            BufferStatus::OK,
+                            nullptr,
+                            nullptr};
+        } else {
+            allocateGraphicBuffer(
+                    testStream.width, testStream.height,
+                    /* We don't look at halStreamConfig.streams[0].consumerUsage
+                     * since that is 0 for output streams
+                     */
+                    android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
+                                                    GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
+                    halStreamConfig.streams[0].overrideFormat, &buffer_handle);
+            outputBuffer = {halStreamConfig.streams[0].id,
+                            bufferId,
+                            buffer_handle,
+                            BufferStatus::OK,
+                            nullptr,
+                            nullptr};
+        }
+        ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {outputBuffer};
+        StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
+        CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */, settings, emptyInputBuffer,
+                                  outputBuffers};
+
+        {
+            std::unique_lock<std::mutex> l(mLock);
+            mInflightMap.clear();
+            mInflightMap.add(frameNumber, &inflightReq);
+        }
+
+        Status status = Status::INTERNAL_ERROR;
+        uint32_t numRequestProcessed = 0;
+        hidl_vec<BufferCache> cachesToRemove;
+        Return<void> returnStatus = session->processCaptureRequest(
+                {request}, cachesToRemove, [&status, &numRequestProcessed](auto s, uint32_t n) {
+                    status = s;
+                    numRequestProcessed = n;
+                });
+        ASSERT_TRUE(returnStatus.isOk());
+        ASSERT_EQ(Status::OK, status);
+        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);
+            ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].buffer.streamId);
+            ASSERT_TRUE(inflightReq.shutterReadoutTimestampValid);
+            nsecs_t readoutTimestamp = inflightReq.shutterReadoutTimestamp;
+
+            if (previewStabilizationOn) {
+                // Here we collect the time difference between the buffer ready
+                // timestamp - notify readout timestamp.
+                // timeLag = buffer ready timestamp - notify readout timestamp.
+                // timeLag(previewStabilization) must be <=
+                //        timeLag(stabilization off) + 1 frame duration.
+                auto it = cameraDeviceToTimeLag.find(name.c_str());
+                camera_metadata_entry e;
+                e = inflightReq.collectedResult.find(ANDROID_SENSOR_FRAME_DURATION);
+                ASSERT_TRUE(e.count > 0);
+                nsecs_t frameDuration = e.data.i64[0];
+                ASSERT_TRUE(it != cameraDeviceToTimeLag.end());
+
+                nsecs_t previewStabOnLagTime =
+                        inflightReq.resultOutputBuffers[0].timeStamp - readoutTimestamp;
+                ASSERT_TRUE(previewStabOnLagTime <= (it->second + frameDuration));
+            } else {
+                // Fill in the buffer ready timestamp - notify timestamp;
+                cameraDeviceToTimeLag[std::string(name.c_str())] =
+                        inflightReq.resultOutputBuffers[0].timeStamp - readoutTimestamp;
+            }
         }
 
         if (useHalBufManager) {
@@ -5347,7 +5781,7 @@
 
             ASSERT_FALSE(inflightReqs[i].errorCodeValid);
             ASSERT_NE(inflightReqs[i].resultOutputBuffers.size(), 0u);
-            ASSERT_EQ(previewStream.id, inflightReqs[i].resultOutputBuffers[0].streamId);
+            ASSERT_EQ(previewStream.id, inflightReqs[i].resultOutputBuffers[0].buffer.streamId);
             ASSERT_FALSE(inflightReqs[i].collectedResult.isEmpty());
             ASSERT_TRUE(inflightReqs[i].collectedResult.exists(ANDROID_SENSOR_SENSITIVITY));
             camera_metadata_entry_t isoResult = inflightReqs[i].collectedResult.find(
@@ -5631,7 +6065,7 @@
 
             ASSERT_FALSE(inflightReqs[i].errorCodeValid);
             ASSERT_NE(inflightReqs[i].resultOutputBuffers.size(), 0u);
-            ASSERT_EQ(stream.id, inflightReqs[i].resultOutputBuffers[0].streamId);
+            ASSERT_EQ(stream.id, inflightReqs[i].resultOutputBuffers[0].buffer.streamId);
             ASSERT_FALSE(inflightReqs[i].collectedResult.isEmpty());
         }
 
@@ -5827,7 +6261,7 @@
 
             if (!inflightReq.errorCodeValid) {
                 ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-                ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
+                ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].buffer.streamId);
             } else {
                 switch (inflightReq.errorCode) {
                     case ErrorCode::ERROR_REQUEST:
@@ -6222,6 +6656,7 @@
         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:
@@ -6512,6 +6947,22 @@
     return ret;
 }
 
+bool CameraHidlTest::isTorchStrengthControlSupported(const camera_metadata_t *staticMetadata) {
+    int32_t maxLevel = 0;
+    camera_metadata_ro_entry maxEntry;
+    int rc = find_camera_metadata_ro_entry(staticMetadata,
+            ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL, &maxEntry);
+    if (rc != 0) {
+        return false;
+    }
+    maxLevel = *maxEntry.data.i32;
+    if (maxLevel > 1) {
+        ALOGI("Torch strength control supported.");
+        return true;
+    }
+    return false;
+}
+
 // Check if the camera device has logical multi-camera capability.
 Status CameraHidlTest::isOfflineSessionSupported(const camera_metadata_t *staticMeta) {
     Status ret = Status::METHOD_NOT_SUPPORTED;
@@ -7448,6 +7899,47 @@
                           previewStream, halStreamConfig, supportsPartialResults,
                           partialResultCount, useHalBufManager, outCb, streamConfigCounter);
 }
+
+bool CameraHidlTest::supportsPreviewStabilization(const std::string& name,
+                                                  sp<ICameraProvider> provider) {
+    Return<void> ret;
+    sp<ICameraDevice> device3_x = nullptr;
+    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;
+    });
+    if (!(ret.isOk())) {
+        ADD_FAILURE() << "Failed to get camera device interface for " << name;
+    }
+
+    camera_metadata_t* staticMeta = nullptr;
+    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()));
+    });
+    if (!(ret.isOk())) {
+        ADD_FAILURE() << "Failed to get camera characteristics for " << name;
+    }
+    // Go through the characteristics and see if video stabilization modes have
+    // preview stabilization
+    camera_metadata_ro_entry entry;
+
+    int retcode = find_camera_metadata_ro_entry(
+            staticMeta, ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, &entry);
+    if ((0 == retcode) && (entry.count > 0)) {
+        for (auto i = 0; i < entry.count; i++) {
+            if (entry.data.u8[i] ==
+                ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
 // Open a device session and configure a preview stream.
 void CameraHidlTest::configureSingleStream(
         const std::string& name, int32_t deviceVersion, sp<ICameraProvider> provider,
@@ -7651,6 +8143,7 @@
     ASSERT_NE(nullptr, device3_7);
 
     switch (deviceVersion) {
+        case CAMERA_DEVICE_API_VERSION_3_8:
         case CAMERA_DEVICE_API_VERSION_3_7: {
             auto castResult = device::V3_7::ICameraDevice::castFrom(device);
             ASSERT_TRUE(castResult.isOk());
@@ -7707,6 +8200,7 @@
     ASSERT_NE(nullptr, session3_7);
 
     switch (deviceVersion) {
+        case CAMERA_DEVICE_API_VERSION_3_8:
         case CAMERA_DEVICE_API_VERSION_3_7: {
             auto castResult = device::V3_7::ICameraDeviceSession::castFrom(session);
             ASSERT_TRUE(castResult.isOk());
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index fcff6bc..c480c13 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -85,12 +85,19 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.automotive.vehicle</name>
+        <interface>
+            <name>IVehicle</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.automotive.vehicle</name>
         <version>2.0</version>
         <interface>
             <name>IVehicle</name>
-            <instance>default</instance>
+            <regex-instance>.*</regex-instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
@@ -118,6 +125,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.biometrics.fingerprint</name>
+        <version>2</version>
         <interface>
             <name>IFingerprint</name>
             <instance>default</instance>
@@ -139,6 +147,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.bluetooth.audio</name>
+        <interface>
+            <name>IBluetoothAudioProviderFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.boot</name>
         <version>1.2</version>
@@ -187,11 +202,10 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
+    <hal format="aidl" optional="true">
         <name>android.hardware.contexthub</name>
-        <version>1.2</version>
         <interface>
-            <name>IContexthub</name>
+            <name>IContextHub</name>
             <instance>default</instance>
         </interface>
     </hal>
@@ -232,11 +246,20 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.gnss</name>
+        <version>2</version>
         <interface>
             <name>IGnss</name>
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.gnss.visibility_control</name>
+        <version>1</version>
+        <interface>
+            <name>IGnssVisibilityControl</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 -->
@@ -256,6 +279,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.graphics.composer3</name>
+        <version>1</version>
+        <interface>
+            <name>IComposer</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.graphics.mapper</name>
         <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
@@ -292,6 +323,13 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
+        <name>android.hardware.net.nlinterceptor</name>
+        <interface>
+            <name>IInterceptor</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
         <name>android.hardware.oemlock</name>
         <version>1</version>
         <interface>
@@ -428,7 +466,7 @@
     </hal>
     <hal format="aidl" optional="false">
         <name>android.hardware.power</name>
-        <version>1-2</version>
+        <version>1-3</version>
         <interface>
             <name>IPower</name>
             <instance>default</instance>
@@ -605,6 +643,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+         <name>android.hardware.soundtrigger3</name>
+         <version>1</version>
+         <interface>
+             <name>ISoundTriggerHw</name>
+             <instance>default</instance>
+         </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.tetheroffload.config</name>
         <version>1.0</version>
@@ -653,6 +699,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.tv.tuner</name>
+        <version>1</version>
+        <interface>
+            <name>ITuner</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.usb</name>
         <version>1.0-3</version>
@@ -709,6 +763,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.uwb</name>
+        <version>1</version>
+        <interface>
+            <name>IUwb</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi.hostapd</name>
         <version>1.0-3</version>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index d8c9170..2aa4bb2 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -51,12 +51,14 @@
             "android.hardware.media.bufferpool@2.0",
             "android.hardware.radio.config@1.2",
             // AIDL
+            "android.hardware.audio.common",
             "android.hardware.biometrics.common",
             "android.hardware.common",
             "android.hardware.common.fmq",
             "android.hardware.graphics.common",
             "android.hardware.keymaster",
             "android.hardware.radio",
+            "android.hardware.uwb.fira_android",
 
             // Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
             // does not depend on this HAL, hence it is not declared in any manifests or matrices.
diff --git a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
index 356ad97..b3173ef 100644
--- a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
+++ b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
@@ -18,7 +18,8 @@
 
 #include "ContexthubCallbackBase.h"
 #include "ContexthubHidlTestBase.h"
-#include "VtsHalContexthubUtils.h"
+#include "VtsHalContexthubUtilsCommon.h"
+#include "VtsHalContexthubUtilsHidl.h"
 
 #include <android-base/logging.h>
 #include <android/hardware/contexthub/1.0/IContexthub.h>
diff --git a/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp b/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp
index acf4be0..0589fd8 100644
--- a/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp
+++ b/contexthub/1.1/vts/functional/VtsHalContexthubV1_1TargetTest.cpp
@@ -18,7 +18,8 @@
 
 #include "ContexthubCallbackBase.h"
 #include "ContexthubHidlTestBase.h"
-#include "VtsHalContexthubUtils.h"
+#include "VtsHalContexthubUtilsCommon.h"
+#include "VtsHalContexthubUtilsHidl.h"
 
 #include <android-base/logging.h>
 #include <android/hardware/contexthub/1.0/IContexthub.h>
diff --git a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
index 9ee40ed..f1f9807 100644
--- a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
+++ b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
@@ -18,7 +18,8 @@
 
 #include "ContexthubCallbackBase.h"
 #include "ContexthubHidlTestBase.h"
-#include "VtsHalContexthubUtils.h"
+#include "VtsHalContexthubUtilsCommon.h"
+#include "VtsHalContexthubUtilsHidl.h"
 
 #include <android-base/logging.h>
 #include <android/hardware/contexthub/1.0/IContexthub.h>
diff --git a/contexthub/aidl/Android.bp b/contexthub/aidl/Android.bp
new file mode 100644
index 0000000..e9143b5
--- /dev/null
+++ b/contexthub/aidl/Android.bp
@@ -0,0 +1,37 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.contexthub",
+    vendor_available: true,
+    srcs: ["android/hardware/contexthub/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            apps_enabled: false,
+        },
+    },
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/AsyncEventType.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/AsyncEventType.aidl
new file mode 100644
index 0000000..8e0ff89
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/AsyncEventType.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@Backing(type="int") @VintfStability
+enum AsyncEventType {
+  RESTARTED = 1,
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubInfo.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubInfo.aidl
new file mode 100644
index 0000000..e573556
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubInfo.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@VintfStability
+parcelable ContextHubInfo {
+  String name;
+  String vendor;
+  String toolchain;
+  int id;
+  float peakMips;
+  int maxSupportedMessageLengthBytes;
+  long chrePlatformId;
+  byte chreApiMajorVersion;
+  byte chreApiMinorVersion;
+  char chrePatchVersion;
+  String[] supportedPermissions;
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubMessage.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubMessage.aidl
new file mode 100644
index 0000000..e38c251
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/ContextHubMessage.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@VintfStability
+parcelable ContextHubMessage {
+  long nanoappId;
+  char hostEndPoint;
+  int messageType;
+  byte[] messageBody;
+  String[] permissions;
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/HostEndpointInfo.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/HostEndpointInfo.aidl
new file mode 100644
index 0000000..e7dcbc7
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/HostEndpointInfo.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@VintfStability
+parcelable HostEndpointInfo {
+  char hostEndpointId;
+  android.hardware.contexthub.HostEndpointInfo.Type type;
+  @nullable String packageName;
+  @nullable String attributionTag;
+  @Backing(type="int") @VintfStability
+  enum Type {
+    TYPE_FRAMEWORK = 1,
+    TYPE_APP = 2,
+  }
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
new file mode 100644
index 0000000..facce4b
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@VintfStability
+interface IContextHub {
+  List<android.hardware.contexthub.ContextHubInfo> getContextHubs();
+  boolean loadNanoapp(in int contextHubId, in android.hardware.contexthub.NanoappBinary appBinary, in int transactionId);
+  boolean unloadNanoapp(in int contextHubId, in long appId, in int transactionId);
+  boolean disableNanoapp(in int contextHubId, in long appId, in int transactionId);
+  boolean enableNanoapp(in int contextHubId, in long appId, in int transactionId);
+  void onSettingChanged(in android.hardware.contexthub.Setting setting, in boolean enabled);
+  boolean queryNanoapps(in int contextHubId);
+  boolean registerCallback(in int contextHubId, in android.hardware.contexthub.IContextHubCallback cb);
+  boolean sendMessageToHub(in int contextHubId, in android.hardware.contexthub.ContextHubMessage message);
+  void onHostEndpointConnected(in android.hardware.contexthub.HostEndpointInfo hostEndpointInfo);
+  void onHostEndpointDisconnected(char hostEndpointId);
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHubCallback.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHubCallback.aidl
new file mode 100644
index 0000000..f81f7cf
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHubCallback.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@VintfStability
+interface IContextHubCallback {
+  void handleNanoappInfo(in android.hardware.contexthub.NanoappInfo[] appInfo);
+  void handleContextHubMessage(in android.hardware.contexthub.ContextHubMessage msg, in String[] msgContentPerms);
+  void handleContextHubAsyncEvent(in android.hardware.contexthub.AsyncEventType evt);
+  void handleTransactionResult(in int transactionId, in boolean success);
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/NanoappBinary.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/NanoappBinary.aidl
new file mode 100644
index 0000000..d53b28f
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/NanoappBinary.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@VintfStability
+parcelable NanoappBinary {
+  long nanoappId;
+  int nanoappVersion;
+  int flags;
+  byte targetChreApiMajorVersion;
+  byte targetChreApiMinorVersion;
+  byte[] customBinary;
+  const int FLAG_SIGNED = 1;
+  const int FLAG_ENCRYPTED = 2;
+  const int FLAG_TCM_CAPABLE = 4;
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/NanoappInfo.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/NanoappInfo.aidl
new file mode 100644
index 0000000..7175d7f
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/NanoappInfo.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@VintfStability
+parcelable NanoappInfo {
+  long nanoappId;
+  int nanoappVersion;
+  boolean enabled;
+  String[] permissions;
+  android.hardware.contexthub.NanoappRpcService[] rpcServices;
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/NanoappRpcService.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/NanoappRpcService.aidl
new file mode 100644
index 0000000..a6a1644
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/NanoappRpcService.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@VintfStability
+parcelable NanoappRpcService {
+  long id;
+  int version;
+}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Setting.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Setting.aidl
new file mode 100644
index 0000000..41bc9ae
--- /dev/null
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Setting.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.contexthub;
+@Backing(type="byte") @VintfStability
+enum Setting {
+  LOCATION = 1,
+  WIFI_MAIN = 2,
+  WIFI_SCANNING = 3,
+  AIRPLANE_MODE = 4,
+  MICROPHONE = 5,
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/AsyncEventType.aidl b/contexthub/aidl/android/hardware/contexthub/AsyncEventType.aidl
new file mode 100644
index 0000000..d884c9c
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/AsyncEventType.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+@VintfStability
+@Backing(type="int")
+enum AsyncEventType {
+    /** An event where the Context Hub has restarted (e.g. due to a crash). */
+    RESTARTED = 1,
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/ContextHubInfo.aidl b/contexthub/aidl/android/hardware/contexthub/ContextHubInfo.aidl
new file mode 100644
index 0000000..c0fa702
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/ContextHubInfo.aidl
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+@VintfStability
+parcelable ContextHubInfo {
+    /** Descriptive name of the Context Hub */
+    String name;
+
+    /** The vendor e.g. "Google" */
+    String vendor;
+
+    /** Toolchain that describes the binary architecture eg: "gcc ARM" */
+    String toolchain;
+
+    /** A unique ID for this Context Hub */
+    int id;
+
+    /** Peak MIPs this platform can deliver */
+    float peakMips;
+
+    /** The maximum length in bytes of the message that can be sent to the Context Hub. */
+    int maxSupportedMessageLengthBytes;
+
+    /**
+     * Machine-readable CHRE platform ID, returned to nanoapps in the CHRE API
+     * function call chreGetPlatformId(). This field pairs with
+     * chreApiMajorVersion, chreApiMinorVersion, and chrePatchVersion to fully
+     * specify the CHRE implementation version. See also the CHRE API header
+     * file chre/version.h.
+     */
+    long chrePlatformId;
+
+    /**
+     * The version of the CHRE implementation returned to nanoApps in the CHRE
+     *  API function call chreGetVersion(). The major and minor version specify
+     * the implemented version of the CHRE API, while the patch version
+     * describes the implementation version within the scope of the platform
+     * ID. See also the CHRE API header file chre/version.h.
+     */
+    byte chreApiMajorVersion;
+    byte chreApiMinorVersion;
+    char chrePatchVersion;
+
+    /**
+     * A list of Android permissions this Context Hub support for nanoapps to enforce host endpoints
+     * are granted in order to communicate with them.
+     */
+    String[] supportedPermissions;
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/ContextHubMessage.aidl b/contexthub/aidl/android/hardware/contexthub/ContextHubMessage.aidl
new file mode 100644
index 0000000..867da2f
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/ContextHubMessage.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.contexthub;
+
+@VintfStability
+parcelable ContextHubMessage {
+    /** The unique identifier of the nanoapp. */
+    long nanoappId;
+
+    /**
+     * The identifier of the host client that is sending/receiving this message.
+     *
+     * There are two reserved values of the host endpoint that has a specific meaning:
+     * 1) BROADCAST = 0xFFFF: see CHRE_HOST_ENDPOINT_BROADCAST in
+     *    system/chre/chre_api/include/chre_api/chre/event.h for details.
+     * 2) UNSPECIFIED = 0xFFFE: see CHRE_HOST_ENDPOINT_UNSPECIFIED in
+     *    system/chre/chre_api/include/chre_api/chre/event.h for details.
+     */
+    char hostEndPoint;
+
+    /** The type of this message */
+    int messageType;
+
+    /** The payload containing the message */
+    byte[] messageBody;
+
+    /**
+     * The list of Android permissions held by the sending nanoapp at the time
+     * the message was sent.
+     *
+     * The framework MUST drop messages to host apps that don't have a superset
+     * of the permissions that the sending nanoapp is using.
+     */
+    String[] permissions;
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/HostEndpointInfo.aidl b/contexthub/aidl/android/hardware/contexthub/HostEndpointInfo.aidl
new file mode 100644
index 0000000..40a231d
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/HostEndpointInfo.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.contexthub;
+
+/**
+ * Stores metadata regarding a host endpoint that may communicate with the Context Hub.
+ */
+@VintfStability
+parcelable HostEndpointInfo {
+    /** The ID of the host endpoint asscociated with this host. */
+    char hostEndpointId;
+
+    /** The type of endpoint. */
+    Type type;
+
+    /** The (optional) package name of the host. */
+    @nullable String packageName;
+
+    /** The (optional) attribution tag associated with this host. */
+    @nullable String attributionTag;
+
+    @VintfStability
+    @Backing(type="int")
+    enum Type {
+        /**
+           This endpoint is from the Android framework, where packageName and attributionTag may be
+           empty.
+         */
+        TYPE_FRAMEWORK = 1,
+
+        /** This endpoint is an Android app. */
+        TYPE_APP = 2,
+    }
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
new file mode 100644
index 0000000..33d241a
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+import android.hardware.contexthub.ContextHubInfo;
+import android.hardware.contexthub.ContextHubMessage;
+import android.hardware.contexthub.HostEndpointInfo;
+import android.hardware.contexthub.IContextHubCallback;
+import android.hardware.contexthub.NanoappBinary;
+import android.hardware.contexthub.Setting;
+
+@VintfStability
+interface IContextHub {
+    /**
+     * Enumerates all available Context Hubs.
+     *
+     * @return A list of ContextHubInfo describing all Context Hubs.
+     */
+    List<ContextHubInfo> getContextHubs();
+
+    /**
+     * Loads a nanoapp, and invokes the nanoapp's initialization "start()" entrypoint.
+     *
+     * The return value of this method only indicates that the request has been accepted.
+     * If true is returned, the Context Hub must handle an asynchronous result using the
+     * the handleTransactionResult() callback.
+     *
+     * Depending on the implementation, nanoapp loaded via this API may or may
+     * not persist across reboots of the hub. If they do persist, the
+     * implementation must initially place nanoapp in the disabled state upon a
+     * reboot, and not start them until a call is made to enableNanoapp(). In
+     * this case, the app must also be unloaded upon a factory reset of the
+     * device.
+     *
+     * Loading a nanoapp must not take more than 30 seconds.
+     *
+     * @param contextHubId The identifier of the Context Hub
+     * @param appBinary The nanoapp binary with header
+     * @param transactionId The transaction ID associated with this request
+     *
+     * @return The return code
+     */
+    boolean loadNanoapp(in int contextHubId, in NanoappBinary appBinary, in int transactionId);
+
+    /**
+     * Invokes the nanoapp's deinitialization "end()" entrypoint, and unloads the nanoapp.
+     *
+     * The return value of this method only indicates that the request has been accepted.
+     * If true is returned, the Context Hub must handle an asynchronous result using the
+     * the handleTransactionResult() callback.
+     *
+     * Unloading a nanoapp must not take more than 5 seconds.
+     *
+     * @param contextHubId The identifier of the Context Hub
+     * @param appId The unique ID of the nanoapp
+     * @param transactionId The transaction ID associated with this request
+     *
+     * @return The return code
+     */
+    boolean unloadNanoapp(in int contextHubId, in long appId, in int transactionId);
+
+    /**
+     * Disables a nanoapp by invoking the nanoapp's "end()" entrypoint, but does not unload the
+     * nanoapp.
+     *
+     * The return value of this method only indicates that the request has been accepted.
+     * If true is returned, the Context Hub must handle an asynchronous result using the
+     * the handleTransactionResult() callback.
+     *
+     * Disabling a nanoapp must not take more than 5 seconds.
+     *
+     * @param contextHubId The identifier of the Context Hub
+     * @param appId The unique ID of the nanoapp
+     * @param transactionId The transaction ID associated with this request
+     *
+     * @return The return code
+     */
+    boolean disableNanoapp(in int contextHubId, in long appId, in int transactionId);
+
+    /**
+     * Enables a nanoapp by invoking the nanoapp's initialization "start()" entrypoint.
+     *
+     * The return value of this method only indicates that the request has been accepted.
+     * If true is returned, the Context Hub must handle an asynchronous result using the
+     * the handleTransactionResult() callback.
+     *
+     * Enabling a nanoapp must not take more than 5 seconds.
+     *
+     * @param contextHubId The identifier of the Context Hub
+     * @param appId appIdentifier returned by the HAL
+     * @param message   message to be sent
+     *
+     * @return true on success
+     */
+    boolean enableNanoapp(in int contextHubId, in long appId, in int transactionId);
+
+    /**
+     * Notification sent by the framework to indicate that the user has changed a setting.
+     *
+     * @param setting User setting that has been modified
+     * @param enabled true if the setting has been enabled, false otherwise
+     */
+    void onSettingChanged(in Setting setting, in boolean enabled);
+
+    /**
+     * Queries for a list of loaded nanoapps on a Context Hub.
+     *
+     * If this method succeeds, the result of the query must be delivered through the
+     * handleNanoappInfo() callback.
+     *
+     * @param contextHubId The identifier of the Context Hub
+     *
+     * @return true on success
+     */
+    boolean queryNanoapps(in int contextHubId);
+
+    /**
+     * Register a callback for the HAL implementation to send asynchronous messages to the service
+     * from a Context hub. There can only be one callback registered for a single Context Hub ID.
+     *
+     * A call to this function when a callback has already been registered must override the
+     * previous registration.
+     *
+     * @param contextHubId The identifier of the Context Hub
+     * @param callback an implementation of the IContextHubCallbacks
+     *
+     * @return true on success
+     *
+     */
+    boolean registerCallback(in int contextHubId, in IContextHubCallback cb);
+
+    /**
+     * Sends a message targeted to a nanoapp to the Context Hub.
+     *
+     * @param contextHubId The identifier of the Context Hub
+     * @param message The message to be sent
+     *
+     * @return true on success
+     */
+    boolean sendMessageToHub(in int contextHubId, in ContextHubMessage message);
+
+    /**
+     * Invoked when a host endpoint has connected with the ContextHubService.
+     *
+     * The host associated with this invocation may initiate a communication channel with
+     * the Context Hub using sendMessageToHub.
+     *
+     * @param hostEndpointInfo Metadata associated with this host endpoint.
+     */
+    void onHostEndpointConnected(in HostEndpointInfo hostEndpointInfo);
+
+    /**
+     * Invoked when a host endpoint has disconnected from the framework. This could be as a result
+     * of an explicit connection closure, or unexpected restarts.
+     *
+     * Note that hostEndpointId is the same as the value in HostEndpointInfo. When this function is
+     * called, the HAL is expected to clean up any resources attached to the messaging channel
+     * associated with this host endpoint ID.
+     *
+     * @param hostEndPointId The ID of the host that has disconnected.
+     *
+     * @return Status::ok on success
+     *         EX_ILLEGAL_ARGUMENT if hostEndpointId is not associated with a connected host.
+     */
+    void onHostEndpointDisconnected(char hostEndpointId);
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/IContextHubCallback.aidl b/contexthub/aidl/android/hardware/contexthub/IContextHubCallback.aidl
new file mode 100644
index 0000000..e385d48
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/IContextHubCallback.aidl
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+import android.hardware.contexthub.AsyncEventType;
+import android.hardware.contexthub.ContextHubMessage;
+import android.hardware.contexthub.NanoappInfo;
+
+@VintfStability
+interface IContextHubCallback {
+    /**
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send information about the
+     * currently loaded and active nanoapps on the hub.
+     *
+     * @param appInfo vector of HubAppinfo structure for each nanoApp
+     *                on the hub that can be enabled, disabled and
+     *                unloaded by the service. Any nanoApps that cannot
+     *                be controlled by the service must not be reported.
+     *                All nanoApps that can be controlled by the service
+     *                must be reported.
+     */
+    void handleNanoappInfo(in NanoappInfo[] appInfo);
+
+    /**
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send asynchronous messages back
+     * to the service and registered clients of the ContextHub service.
+     *
+     * @param msg             message that should be delivered to host app
+     *                        clients
+     * @param msgContentPerms list of Android permissions that cover the
+     *                        contents of the message being sent from the app.
+     *                        This is different from the permissions stored
+     *                        inside of ContextHubMsg in that these must be a
+     *                        subset of those permissions and are meant to
+     *                        assist in properly attributing the message
+     *                        contents when delivering to a ContextHub service
+     *                        client.
+     */
+    void handleContextHubMessage(in ContextHubMessage msg, in String[] msgContentPerms);
+
+    /**
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send an asynchronous event
+     * to the ContextHub service.
+     *
+     * @param evt event being sent from the contexthub
+     *
+     */
+    void handleContextHubAsyncEvent(in AsyncEventType evt);
+
+    /**
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send the response for a
+     * transaction.
+     *
+     * @param transactionId The ID of the transaction associated with this callback
+     * @param success true if the transaction succeeded, false otherwise
+     *
+     */
+    void handleTransactionResult(in int transactionId, in boolean success);
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/NanoappBinary.aidl b/contexthub/aidl/android/hardware/contexthub/NanoappBinary.aidl
new file mode 100644
index 0000000..c677ca6
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/NanoappBinary.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+@VintfStability
+parcelable NanoappBinary {
+    /** Indicates that the nanoapp is securely signed (e.g. for production) */
+    const int FLAG_SIGNED = 1 << 0;
+    const int FLAG_ENCRYPTED = 1 << 1;
+    /** Indicates that the nanoapp can run on a Context Hub's TCM memory region */
+    const int FLAG_TCM_CAPABLE = 1 << 2;
+
+    /**
+     * The unique identifier of the nanoapp for the entire system. See chreNanoappInfo in
+     * system/chre/chre_api/include/chre_api/chre/event.h for the convention for choosing
+     * this ID.
+     */
+    long nanoappId;
+
+    /** The version of the nanoapp. */
+    int nanoappVersion;
+
+    /** The nanoapp flags, comprised of the bitmasks defined in FLAG_* constants above. */
+    int flags;
+
+    /**
+     * The version of the CHRE API that this nanoapp was compiled against. See
+     * the CHRE API header file chre/version.h for more information. The hub
+     * implementation must use this to confirm compatibility before loading
+     * this nanoapp.
+     */
+    byte targetChreApiMajorVersion;
+    byte targetChreApiMinorVersion;
+
+    /**
+     * Implementation-specific binary nanoapp data. This does not include the
+     * common nanoapp header that contains the app ID, etc., as this data is
+     * explicitly passed through the other fields in this struct.
+     */
+    byte[] customBinary;
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/NanoappInfo.aidl b/contexthub/aidl/android/hardware/contexthub/NanoappInfo.aidl
new file mode 100644
index 0000000..77ac026
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/NanoappInfo.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.contexthub;
+
+import android.hardware.contexthub.NanoappRpcService;
+
+@VintfStability
+parcelable NanoappInfo {
+    /** The unique identifier of the nanoapp. */
+    long nanoappId;
+
+    /** The version of the nanoapp */
+    int nanoappVersion;
+
+    /** True if this nanoapp is in a running state, false otherwise */
+    boolean enabled;
+
+    /**
+     * The list of Android permissions used by this nanoapp. This list MUST
+     * correspond to the permissions required for an equivalent Android app to
+     * sample similar signals through the Android framework.
+     *
+     * For example, if a nanoapp used location-based signals, the permissions
+     * list MUST contains android.permission.ACCESS_FINE_LOCATION and
+     * android.permission.ACCESS_BACKGROUND_LOCATION. If it were to also use
+     * audio data, it would require adding android.permission.RECORD_AUDIO to
+     * this list.
+     */
+    String[] permissions;
+
+    /**
+     * The list of RPC services supported by this nanoapp.
+     */
+    NanoappRpcService[] rpcServices;
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/NanoappRpcService.aidl b/contexthub/aidl/android/hardware/contexthub/NanoappRpcService.aidl
new file mode 100644
index 0000000..6dc5e95
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/NanoappRpcService.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.contexthub;
+
+/**
+ * An RPC service exposed by a nanoapp.
+ *
+ * The implementation of the RPC interface is not defined by the HAL, and is written
+ * at the messaging endpoint layers (Android app and/or CHRE nanoapp). NanoappRpcService
+ * contains the informational metadata to be consumed by the RPC interface layer.
+ */
+@VintfStability
+parcelable NanoappRpcService {
+    /**
+     * The unique 64-bit ID of an RPC service exposed by a nanoapp. Note that
+     * the uniqueness is only required within the nanoapp's domain (i.e. the
+     * combination of the nanoapp ID and service id must be unique).
+     */
+    long id;
+
+    /**
+     * The software version of this service, which follows the semantic
+     * versioning scheme (see semver.org). It follows the format
+     * major.minor.patch, where major and minor versions take up one byte
+     * each, and the patch version takes up the final 2 bytes.
+     */
+    int version;
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/Setting.aidl b/contexthub/aidl/android/hardware/contexthub/Setting.aidl
new file mode 100644
index 0000000..f2e55db
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/Setting.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.contexthub;
+
+/**
+ * Used to indicate the type of user setting that has changed.
+ */
+@VintfStability
+@Backing(type="byte")
+enum Setting {
+    LOCATION = 1,
+    /**
+     * The main WiFi toggle in the Android settings for WiFi connectivity.
+     */
+    WIFI_MAIN,
+    /**
+     * The "Wi-Fi scanning" setting for location scans.
+     */
+    WIFI_SCANNING,
+    AIRPLANE_MODE,
+    /**
+     * Indicates if the microphone access is available for CHRE. Microphone
+     * access is disabled if the user has turned off the microphone as a
+     * privacy setting, in which case audio data cannot be used and propagated
+     * by CHRE.
+     */
+    MICROPHONE,
+}
diff --git a/contexthub/aidl/default/Android.bp b/contexthub/aidl/default/Android.bp
new file mode 100644
index 0000000..269057a
--- /dev/null
+++ b/contexthub/aidl/default/Android.bp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+    name: "libcontexthubexampleimpl",
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "android.hardware.contexthub-V1-ndk",
+    ],
+    export_include_dirs: ["include"],
+    srcs: [
+        "ContextHub.cpp",
+    ],
+    visibility: [
+        ":__subpackages__",
+        "//hardware/interfaces/tests/extension/contexthub:__subpackages__",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.contexthub-service.example",
+    relative_install_path: "hw",
+    init_rc: ["contexthub-default.rc"],
+    vintf_fragments: ["contexthub-default.xml"],
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "android.hardware.contexthub-V1-ndk",
+    ],
+    static_libs: [
+        "libcontexthubexampleimpl",
+    ],
+    srcs: ["main.cpp"],
+}
diff --git a/contexthub/aidl/default/ContextHub.cpp b/contexthub/aidl/default/ContextHub.cpp
new file mode 100644
index 0000000..6da690d
--- /dev/null
+++ b/contexthub/aidl/default/ContextHub.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "contexthub-impl/ContextHub.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace contexthub {
+
+::ndk::ScopedAStatus ContextHub::getContextHubs(std::vector<ContextHubInfo>* out_contextHubInfos) {
+    ContextHubInfo hub = {};
+    hub.name = "Mock Context Hub";
+    hub.vendor = "AOSP";
+    hub.toolchain = "n/a";
+    hub.id = kMockHubId;
+    hub.peakMips = 1;
+    hub.maxSupportedMessageLengthBytes = 4096;
+    hub.chrePlatformId = UINT64_C(0x476f6f6754000000);
+    hub.chreApiMajorVersion = 1;
+    hub.chreApiMinorVersion = 6;
+
+    out_contextHubInfos->push_back(hub);
+
+    return ndk::ScopedAStatus::ok();
+}
+
+// We don't expose any nanoapps for the default impl, therefore all nanoapp-related APIs fail.
+::ndk::ScopedAStatus ContextHub::loadNanoapp(int32_t /* in_contextHubId */,
+                                             const NanoappBinary& /* in_appBinary */,
+                                             int32_t /* in_transactionId */, bool* _aidl_return) {
+    *_aidl_return = false;
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ContextHub::unloadNanoapp(int32_t /* in_contextHubId */,
+                                               int64_t /* in_appId */,
+                                               int32_t /* in_transactionId */, bool* _aidl_return) {
+    *_aidl_return = false;
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ContextHub::disableNanoapp(int32_t /* in_contextHubId */,
+                                                int64_t /* in_appId */,
+                                                int32_t /* in_transactionId */,
+                                                bool* _aidl_return) {
+    *_aidl_return = false;
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ContextHub::enableNanoapp(int32_t /* in_contextHubId */,
+                                               int64_t /* in_appId */,
+                                               int32_t /* in_transactionId */, bool* _aidl_return) {
+    *_aidl_return = false;
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ContextHub::onSettingChanged(Setting /* in_setting */, bool /*in_enabled */) {
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ContextHub::queryNanoapps(int32_t in_contextHubId, bool* _aidl_return) {
+    if (in_contextHubId == kMockHubId && mCallback != nullptr) {
+        std::vector<NanoappInfo> nanoapps;
+        mCallback->handleNanoappInfo(nanoapps);
+        *_aidl_return = true;
+    } else {
+        *_aidl_return = false;
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ContextHub::registerCallback(int32_t in_contextHubId,
+                                                  const std::shared_ptr<IContextHubCallback>& in_cb,
+                                                  bool* _aidl_return) {
+    if (in_contextHubId == kMockHubId) {
+        mCallback = in_cb;
+        *_aidl_return = true;
+    } else {
+        *_aidl_return = false;
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ContextHub::sendMessageToHub(int32_t in_contextHubId,
+                                                  const ContextHubMessage& /* in_message */,
+                                                  bool* _aidl_return) {
+    if (in_contextHubId == kMockHubId) {
+        // Return true here to indicate that the HAL has accepted the message.
+        // Successful delivery of the message to a nanoapp should be handled at
+        // a higher level protocol.
+        *_aidl_return = true;
+    } else {
+        *_aidl_return = false;
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ContextHub::onHostEndpointConnected(const HostEndpointInfo& in_info) {
+    mConnectedHostEndpoints.insert(in_info.hostEndpointId);
+
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus ContextHub::onHostEndpointDisconnected(char16_t in_hostEndpointId) {
+    if (mConnectedHostEndpoints.count(in_hostEndpointId) > 0) {
+        mConnectedHostEndpoints.erase(in_hostEndpointId);
+        return ndk::ScopedAStatus::ok();
+    } else {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
+    }
+}
+
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/contexthub/aidl/default/contexthub-default.rc b/contexthub/aidl/default/contexthub-default.rc
new file mode 100644
index 0000000..a6a6d2a
--- /dev/null
+++ b/contexthub/aidl/default/contexthub-default.rc
@@ -0,0 +1,4 @@
+service vendor.contexthub-default /vendor/bin/hw/android.hardware.contexthub-service.example
+    class hal
+    user context_hub
+    group context_hub
diff --git a/contexthub/aidl/default/contexthub-default.xml b/contexthub/aidl/default/contexthub-default.xml
new file mode 100644
index 0000000..e383c50
--- /dev/null
+++ b/contexthub/aidl/default/contexthub-default.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.contexthub</name>
+        <version>1</version>
+        <fqname>IContextHub/default</fqname>
+    </hal>
+</manifest>
diff --git a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
new file mode 100644
index 0000000..dd739e6
--- /dev/null
+++ b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/contexthub/BnContextHub.h>
+
+#include <unordered_set>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace contexthub {
+
+class ContextHub : public BnContextHub {
+    ::ndk::ScopedAStatus getContextHubs(std::vector<ContextHubInfo>* out_contextHubInfos) override;
+    ::ndk::ScopedAStatus loadNanoapp(int32_t in_contextHubId, const NanoappBinary& in_appBinary,
+                                     int32_t in_transactionId, bool* _aidl_return) override;
+    ::ndk::ScopedAStatus unloadNanoapp(int32_t in_contextHubId, int64_t in_appId,
+                                       int32_t in_transactionId, bool* _aidl_return) override;
+    ::ndk::ScopedAStatus disableNanoapp(int32_t in_contextHubId, int64_t in_appId,
+                                        int32_t in_transactionId, bool* _aidl_return) override;
+    ::ndk::ScopedAStatus enableNanoapp(int32_t in_contextHubId, int64_t in_appId,
+                                       int32_t in_transactionId, bool* _aidl_return) override;
+    ::ndk::ScopedAStatus onSettingChanged(Setting in_setting, bool in_enabled) override;
+    ::ndk::ScopedAStatus queryNanoapps(int32_t in_contextHubId, bool* _aidl_return) override;
+    ::ndk::ScopedAStatus registerCallback(int32_t in_contextHubId,
+                                          const std::shared_ptr<IContextHubCallback>& in_cb,
+                                          bool* _aidl_return) override;
+    ::ndk::ScopedAStatus sendMessageToHub(int32_t in_contextHubId,
+                                          const ContextHubMessage& in_message,
+                                          bool* _aidl_return) override;
+    ::ndk::ScopedAStatus onHostEndpointConnected(const HostEndpointInfo& in_info) override;
+
+    ::ndk::ScopedAStatus onHostEndpointDisconnected(char16_t in_hostEndpointId) override;
+
+  private:
+    static constexpr uint32_t kMockHubId = 0;
+    std::shared_ptr<IContextHubCallback> mCallback;
+
+    std::unordered_set<char16_t> mConnectedHostEndpoints;
+};
+
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/contexthub/aidl/default/main.cpp b/contexthub/aidl/default/main.cpp
new file mode 100644
index 0000000..dc9035f
--- /dev/null
+++ b/contexthub/aidl/default/main.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "contexthub-impl/ContextHub.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::contexthub::ContextHub;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+    // Make a default contexthub service
+    auto vib = ndk::SharedRefBase::make<ContextHub>();
+    const std::string vibName = std::string() + ContextHub::descriptor + "/default";
+    binder_status_t status = AServiceManager_addService(vib->asBinder().get(), vibName.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reach
+}
diff --git a/contexthub/aidl/vts/Android.bp b/contexthub/aidl/vts/Android.bp
new file mode 100644
index 0000000..673eac0
--- /dev/null
+++ b/contexthub/aidl/vts/Android.bp
@@ -0,0 +1,42 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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: "VtsAidlHalContextHubTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsAidlHalContextHubTargetTest.cpp"],
+    shared_libs: [
+        "libbinder",
+    ],
+    static_libs: [
+        "android.hardware.contexthub-V1-cpp",
+        "VtsHalContexthubUtils",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/contexthub/aidl/vts/OWNERS b/contexthub/aidl/vts/OWNERS
new file mode 100644
index 0000000..150818d
--- /dev/null
+++ b/contexthub/aidl/vts/OWNERS
@@ -0,0 +1 @@
+file:/contexthub/common/vts/OWNERS
diff --git a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
new file mode 100644
index 0000000..392e23c
--- /dev/null
+++ b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include "VtsHalContexthubUtilsCommon.h"
+
+#include <android/hardware/contexthub/BnContextHub.h>
+#include <android/hardware/contexthub/BnContextHubCallback.h>
+#include <android/hardware/contexthub/IContextHub.h>
+#include <android/hardware/contexthub/IContextHubCallback.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <log/log.h>
+
+#include <cinttypes>
+#include <future>
+
+using ::android::ProcessState;
+using ::android::sp;
+using ::android::String16;
+using ::android::binder::Status;
+using ::android::hardware::contexthub::AsyncEventType;
+using ::android::hardware::contexthub::ContextHubInfo;
+using ::android::hardware::contexthub::ContextHubMessage;
+using ::android::hardware::contexthub::HostEndpointInfo;
+using ::android::hardware::contexthub::IContextHub;
+using ::android::hardware::contexthub::IContextHubCallbackDefault;
+using ::android::hardware::contexthub::NanoappBinary;
+using ::android::hardware::contexthub::NanoappInfo;
+using ::android::hardware::contexthub::NanoappRpcService;
+using ::android::hardware::contexthub::Setting;
+using ::android::hardware::contexthub::vts_utils::kNonExistentAppId;
+using ::android::hardware::contexthub::vts_utils::waitForCallback;
+
+class ContextHubAidl : public testing::TestWithParam<std::tuple<std::string, int32_t>> {
+  public:
+    virtual void SetUp() override {
+        contextHub = android::waitForDeclaredService<IContextHub>(
+                String16(std::get<0>(GetParam()).c_str()));
+        ASSERT_NE(contextHub, nullptr);
+    }
+
+    uint32_t getHubId() { return std::get<1>(GetParam()); }
+
+    void testSettingChanged(Setting setting);
+
+    sp<IContextHub> contextHub;
+};
+
+TEST_P(ContextHubAidl, TestGetHubs) {
+    std::vector<ContextHubInfo> hubs;
+    ASSERT_TRUE(contextHub->getContextHubs(&hubs).isOk());
+
+    ALOGD("System reports %zu hubs", hubs.size());
+
+    for (const ContextHubInfo& hub : hubs) {
+        ALOGD("Checking hub ID %" PRIu32, hub.id);
+
+        EXPECT_GT(hub.name.size(), 0);
+        EXPECT_GT(hub.vendor.size(), 0);
+        EXPECT_GT(hub.toolchain.size(), 0);
+        EXPECT_GT(hub.peakMips, 0);
+        EXPECT_GT(hub.chrePlatformId, 0);
+        EXPECT_GT(hub.chreApiMajorVersion, 0);
+        EXPECT_GE(hub.chreApiMinorVersion, 0);
+        EXPECT_GE(hub.chrePatchVersion, 0);
+
+        // Minimum 128 byte MTU as required by CHRE API v1.0
+        EXPECT_GE(hub.maxSupportedMessageLengthBytes, UINT32_C(128));
+    }
+}
+
+class EmptyContextHubCallback : public android::hardware::contexthub::BnContextHubCallback {
+  public:
+    Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
+        return Status::ok();
+    }
+
+    Status handleContextHubMessage(const ContextHubMessage& /* msg */,
+                                   const std::vector<String16>& /* msgContentPerms */) override {
+        return Status::ok();
+    }
+
+    Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
+
+    Status handleTransactionResult(int32_t /* transactionId */, bool /* success */) override {
+        return Status::ok();
+    }
+};
+
+TEST_P(ContextHubAidl, TestRegisterCallback) {
+    bool success;
+    sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
+    ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
+    ASSERT_TRUE(success);
+}
+
+TEST_P(ContextHubAidl, TestRegisterNullCallback) {
+    bool success;
+    ASSERT_TRUE(contextHub->registerCallback(getHubId(), nullptr, &success).isOk());
+}
+
+// Helper callback that puts the async appInfo callback data into a promise
+class QueryAppsCallback : public android::hardware::contexthub::BnContextHubCallback {
+  public:
+    Status handleNanoappInfo(const std::vector<NanoappInfo>& appInfo) override {
+        ALOGD("Got app info callback with %zu apps", appInfo.size());
+        promise.set_value(appInfo);
+        return Status::ok();
+    }
+
+    Status handleContextHubMessage(const ContextHubMessage& /* msg */,
+                                   const std::vector<String16>& /* msgContentPerms */) override {
+        return Status::ok();
+    }
+
+    Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
+
+    Status handleTransactionResult(int32_t /* transactionId */, bool /* success */) override {
+        return Status::ok();
+    }
+
+    std::promise<std::vector<NanoappInfo>> promise;
+};
+
+// Calls queryApps() and checks the returned metadata
+TEST_P(ContextHubAidl, TestQueryApps) {
+    sp<QueryAppsCallback> cb = sp<QueryAppsCallback>::make();
+    bool success;
+    ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
+    ASSERT_TRUE(success);
+
+    ASSERT_TRUE(contextHub->queryNanoapps(getHubId(), &success).isOk());
+    ASSERT_TRUE(success);
+
+    std::vector<NanoappInfo> appInfoList;
+    ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appInfoList));
+    for (const NanoappInfo& appInfo : appInfoList) {
+        EXPECT_NE(appInfo.nanoappId, UINT64_C(0));
+        EXPECT_NE(appInfo.nanoappId, kNonExistentAppId);
+
+        // Verify services are unique.
+        std::set<uint64_t> existingServiceIds;
+        for (const NanoappRpcService& rpcService : appInfo.rpcServices) {
+            EXPECT_NE(rpcService.id, UINT64_C(0));
+            EXPECT_EQ(existingServiceIds.count(rpcService.id), 0);
+            existingServiceIds.insert(rpcService.id);
+        }
+    }
+}
+
+// Helper callback that puts the TransactionResult for the expectedTransactionId into a
+// promise
+class TransactionResultCallback : public android::hardware::contexthub::BnContextHubCallback {
+  public:
+    Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
+        return Status::ok();
+    }
+
+    Status handleContextHubMessage(const ContextHubMessage& /* msg */,
+                                   const std::vector<String16>& /* msgContentPerms */) override {
+        return Status::ok();
+    }
+
+    Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
+
+    Status handleTransactionResult(int32_t transactionId, bool success) override {
+        ALOGD("Got transaction result callback for transactionId %" PRIu32 " (expecting %" PRIu32
+              ") with success %d",
+              transactionId, expectedTransactionId, success);
+        if (transactionId == expectedTransactionId) {
+            promise.set_value(success);
+        }
+        return Status::ok();
+    }
+
+    uint32_t expectedTransactionId = 0;
+    std::promise<bool> promise;
+};
+
+// Parameterized fixture that sets the callback to TransactionResultCallback
+class ContextHubTransactionTest : public ContextHubAidl {
+  public:
+    virtual void SetUp() override {
+        ContextHubAidl::SetUp();
+        bool success;
+        ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
+        ASSERT_TRUE(success);
+    }
+
+    sp<TransactionResultCallback> cb = sp<TransactionResultCallback>::make();
+};
+
+TEST_P(ContextHubTransactionTest, TestSendMessageToNonExistentNanoapp) {
+    ContextHubMessage message;
+    message.nanoappId = kNonExistentAppId;
+    message.messageType = 1;
+    message.messageBody.resize(4);
+    std::fill(message.messageBody.begin(), message.messageBody.end(), 0);
+
+    ALOGD("Sending message to non-existent nanoapp");
+    bool success;
+    ASSERT_TRUE(contextHub->sendMessageToHub(getHubId(), message, &success).isOk());
+    ASSERT_TRUE(success);
+}
+
+TEST_P(ContextHubTransactionTest, TestLoadEmptyNanoapp) {
+    cb->expectedTransactionId = 0123;
+    NanoappBinary emptyApp;
+
+    emptyApp.nanoappId = kNonExistentAppId;
+    emptyApp.nanoappVersion = 1;
+    emptyApp.flags = 0;
+    emptyApp.targetChreApiMajorVersion = 1;
+    emptyApp.targetChreApiMinorVersion = 0;
+
+    ALOGD("Loading empty nanoapp");
+    bool success;
+    ASSERT_TRUE(contextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId, &success)
+                        .isOk());
+    if (success) {
+        bool transactionSuccess;
+        ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
+        ASSERT_FALSE(transactionSuccess);
+    }
+}
+
+TEST_P(ContextHubTransactionTest, TestUnloadNonexistentNanoapp) {
+    cb->expectedTransactionId = 1234;
+
+    ALOGD("Unloading nonexistent nanoapp");
+    bool success;
+    ASSERT_TRUE(contextHub
+                        ->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId,
+                                        &success)
+                        .isOk());
+    if (success) {
+        bool transactionSuccess;
+        ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
+        ASSERT_FALSE(transactionSuccess);
+    }
+}
+
+TEST_P(ContextHubTransactionTest, TestEnableNonexistentNanoapp) {
+    cb->expectedTransactionId = 2345;
+
+    ALOGD("Enabling nonexistent nanoapp");
+    bool success;
+    ASSERT_TRUE(contextHub
+                        ->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId,
+                                        &success)
+                        .isOk());
+    if (success) {
+        bool transactionSuccess;
+        ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
+        ASSERT_FALSE(transactionSuccess);
+    }
+}
+
+TEST_P(ContextHubTransactionTest, TestDisableNonexistentNanoapp) {
+    cb->expectedTransactionId = 3456;
+
+    ALOGD("Disabling nonexistent nanoapp");
+    bool success;
+    ASSERT_TRUE(contextHub
+                        ->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId,
+                                         &success)
+                        .isOk());
+    if (success) {
+        bool transactionSuccess;
+        ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
+        ASSERT_FALSE(transactionSuccess);
+    }
+}
+
+void ContextHubAidl::testSettingChanged(Setting setting) {
+    // In VTS, we only test that sending the values doesn't cause things to blow up - GTS tests
+    // verify the expected E2E behavior in CHRE
+    bool success;
+    sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
+    ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
+    ASSERT_TRUE(success);
+
+    ASSERT_TRUE(contextHub->onSettingChanged(setting, true /* enabled */).isOk());
+    ASSERT_TRUE(contextHub->onSettingChanged(setting, false /* enabled */).isOk());
+
+    ASSERT_TRUE(contextHub->registerCallback(getHubId(), nullptr, &success).isOk());
+    ASSERT_TRUE(success);
+}
+
+TEST_P(ContextHubAidl, TestOnLocationSettingChanged) {
+    testSettingChanged(Setting::LOCATION);
+}
+
+TEST_P(ContextHubAidl, TestOnWifiMainSettingChanged) {
+    testSettingChanged(Setting::WIFI_MAIN);
+}
+
+TEST_P(ContextHubAidl, TestOnWifiScanningSettingChanged) {
+    testSettingChanged(Setting::WIFI_SCANNING);
+}
+
+TEST_P(ContextHubAidl, TestOnAirplaneModeSettingChanged) {
+    testSettingChanged(Setting::AIRPLANE_MODE);
+}
+
+TEST_P(ContextHubAidl, TestOnMicrophoneSettingChanged) {
+    testSettingChanged(Setting::MICROPHONE);
+}
+
+std::vector<std::tuple<std::string, int32_t>> generateContextHubMapping() {
+    std::vector<std::tuple<std::string, int32_t>> tuples;
+    auto contextHubAidlNames = android::getAidlHalInstanceNames(IContextHub::descriptor);
+    std::vector<ContextHubInfo> contextHubInfos;
+
+    for (int i = 0; i < contextHubAidlNames.size(); i++) {
+        auto contextHubName = contextHubAidlNames[i].c_str();
+        auto contextHub = android::waitForDeclaredService<IContextHub>(String16(contextHubName));
+        if (contextHub->getContextHubs(&contextHubInfos).isOk()) {
+            for (auto& info : contextHubInfos) {
+                tuples.push_back(std::make_tuple(contextHubName, info.id));
+            }
+        }
+    }
+
+    return tuples;
+}
+
+TEST_P(ContextHubAidl, TestHostConnection) {
+    constexpr char16_t kHostEndpointId = 1;
+    HostEndpointInfo hostEndpointInfo;
+    hostEndpointInfo.hostEndpointId = kHostEndpointId;
+
+    ASSERT_TRUE(contextHub->onHostEndpointConnected(hostEndpointInfo).isOk());
+    ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
+}
+
+TEST_P(ContextHubAidl, TestInvalidHostConnection) {
+    constexpr char16_t kHostEndpointId = 1;
+
+    Status status = contextHub->onHostEndpointDisconnected(kHostEndpointId);
+    ASSERT_EQ(status.exceptionCode(), android::binder::Status::EX_ILLEGAL_ARGUMENT);
+}
+
+std::string PrintGeneratedTest(const testing::TestParamInfo<ContextHubAidl::ParamType>& info) {
+    return std::string("CONTEXT_HUB_ID_") + std::to_string(std::get<1>(info.param));
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubAidl);
+INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidl, testing::ValuesIn(generateContextHubMapping()),
+                         PrintGeneratedTest);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubTransactionTest);
+INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubTransactionTest,
+                         testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/contexthub/common/vts/VtsHalContexthubUtils.cpp b/contexthub/common/vts/VtsHalContexthubUtils.cpp
index 5033b41..d982325 100644
--- a/contexthub/common/vts/VtsHalContexthubUtils.cpp
+++ b/contexthub/common/vts/VtsHalContexthubUtils.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "VtsHalContexthubUtils.h"
+#include "VtsHalContexthubUtilsHidl.h"
 
 #include <chrono>
 #include <future>
diff --git a/contexthub/common/vts/VtsHalContexthubUtils.h b/contexthub/common/vts/VtsHalContexthubUtils.h
deleted file mode 100644
index dff1865..0000000
--- a/contexthub/common/vts/VtsHalContexthubUtils.h
+++ /dev/null
@@ -1,97 +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.
- */
-#pragma once
-
-#include <android/hardware/contexthub/1.0/IContexthub.h>
-#include <gtest/gtest.h>
-#include <hidl/HidlSupport.h>
-#include <hidl/ServiceManagement.h>
-#include <utils/StrongPointer.h>
-
-#include <chrono>
-#include <future>
-#include <vector>
-
-namespace android {
-namespace hardware {
-namespace contexthub {
-namespace vts_utils {
-
-// App ID with vendor "GoogT" (Google Testing), app identifier 0x555555. This
-// app ID is reserved and must never appear in the list of loaded apps.
-constexpr uint64_t kNonExistentAppId = 0x476f6f6754555555;
-
-#define ASSERT_OK(result) ASSERT_EQ(result, ::android::hardware::contexthub::V1_0::Result::OK)
-#define EXPECT_OK(result) EXPECT_EQ(result, ::android::hardware::contexthub::V1_0::Result::OK)
-
-// Helper that does explicit conversion of an enum class to its underlying/base
-// type. Useful for stream output of enum values.
-template <typename EnumType>
-inline constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
-    return static_cast<typename std::underlying_type<EnumType>::type>(value);
-}
-
-// Synchronously queries IContexthub::getHubs() and returns the result
-hidl_vec<V1_0::ContextHub> getHubsSync(V1_0::IContexthub* hubApi);
-
-// Create a vector of tuples that include each IContexthub service paired with each hub ID it
-// exposes via getHubs(). Each tuple represents a test target that we should run the VTS suite
-// against.
-template <class IContexthubVersion>
-static std::vector<std::tuple<std::string, std::string>> getHalAndHubIdList() {
-    std::vector<std::tuple<std::string, std::string>> parameters;
-    std::vector<std::string> serviceNames =
-            ::android::hardware::getAllHalInstanceNames(IContexthubVersion::descriptor);
-    for (const std::string& serviceName : serviceNames) {
-        sp<IContexthubVersion> hubApi = IContexthubVersion::getService(serviceName);
-        if (hubApi != nullptr) {
-            hidl_vec<V1_0::ContextHub> hubs = getHubsSync(hubApi.get());
-            for (const V1_0::ContextHub& hub : hubs) {
-                parameters.push_back(std::make_tuple(serviceName, std::to_string(hub.hubId)));
-            }
-        }
-    }
-
-    return parameters;
-}
-
-// Wait for a callback to occur (signaled by the given future) up to the
-// provided timeout. If the future is invalid or the callback does not come
-// within the given time, returns false.
-template <class ReturnType>
-bool waitForCallback(std::future<ReturnType> future, ReturnType* result,
-                     std::chrono::milliseconds timeout = std::chrono::seconds(5)) {
-    auto expiration = std::chrono::system_clock::now() + timeout;
-
-    EXPECT_NE(result, nullptr);
-    EXPECT_TRUE(future.valid());
-    if (result != nullptr && future.valid()) {
-        std::future_status status = future.wait_until(expiration);
-        EXPECT_NE(status, std::future_status::timeout) << "Timed out waiting for callback";
-
-        if (status == std::future_status::ready) {
-            *result = future.get();
-            return true;
-        }
-    }
-
-    return false;
-}
-
-}  // namespace vts_utils
-}  // namespace contexthub
-}  // namespace hardware
-}  // namespace android
diff --git a/contexthub/common/vts/VtsHalContexthubUtilsCommon.h b/contexthub/common/vts/VtsHalContexthubUtilsCommon.h
new file mode 100644
index 0000000..8b04e3f
--- /dev/null
+++ b/contexthub/common/vts/VtsHalContexthubUtilsCommon.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+/**
+ * Utils file for any Context Hub VTS code (i.e. not specific to e.g. HIDL).
+ */
+
+#pragma once
+
+#include <chrono>
+#include <future>
+
+namespace android {
+namespace hardware {
+namespace contexthub {
+namespace vts_utils {
+
+// App ID with vendor "GoogT" (Google Testing), app identifier 0x555555. This
+// app ID is reserved and must never appear in the list of loaded apps.
+constexpr uint64_t kNonExistentAppId = 0x476f6f6754555555;
+
+// Helper that does explicit conversion of an enum class to its underlying/base
+// type. Useful for stream output of enum values.
+template <typename EnumType>
+inline constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
+    return static_cast<typename std::underlying_type<EnumType>::type>(value);
+}
+
+// Wait for a callback to occur (signaled by the given future) up to the
+// provided timeout. If the future is invalid or the callback does not come
+// within the given time, returns false.
+template <class ReturnType>
+bool waitForCallback(std::future<ReturnType> future, ReturnType* result,
+                     std::chrono::milliseconds timeout = std::chrono::seconds(5)) {
+    auto expiration = std::chrono::system_clock::now() + timeout;
+
+    EXPECT_NE(result, nullptr);
+    EXPECT_TRUE(future.valid());
+    if (result != nullptr && future.valid()) {
+        std::future_status status = future.wait_until(expiration);
+        EXPECT_NE(status, std::future_status::timeout) << "Timed out waiting for callback";
+
+        if (status == std::future_status::ready) {
+            *result = future.get();
+            return true;
+        }
+    }
+
+    return false;
+}
+
+}  // namespace vts_utils
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
diff --git a/contexthub/common/vts/VtsHalContexthubUtilsHidl.h b/contexthub/common/vts/VtsHalContexthubUtilsHidl.h
new file mode 100644
index 0000000..c79afc8
--- /dev/null
+++ b/contexthub/common/vts/VtsHalContexthubUtilsHidl.h
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+/**
+ * Utils file for HIDL related VTS code.
+ */
+#pragma once
+
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/ServiceManagement.h>
+#include <utils/StrongPointer.h>
+
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace contexthub {
+namespace vts_utils {
+
+#define ASSERT_OK(result) ASSERT_EQ(result, ::android::hardware::contexthub::V1_0::Result::OK)
+#define EXPECT_OK(result) EXPECT_EQ(result, ::android::hardware::contexthub::V1_0::Result::OK)
+
+// Synchronously queries IContexthub::getHubs() and returns the result
+hidl_vec<V1_0::ContextHub> getHubsSync(V1_0::IContexthub* hubApi);
+
+// Create a vector of tuples that include each IContexthub service paired with each hub ID it
+// exposes via getHubs(). Each tuple represents a test target that we should run the VTS suite
+// against.
+template <class IContexthubVersion>
+static std::vector<std::tuple<std::string, std::string>> getHalAndHubIdList() {
+    std::vector<std::tuple<std::string, std::string>> parameters;
+    std::vector<std::string> serviceNames =
+            ::android::hardware::getAllHalInstanceNames(IContexthubVersion::descriptor);
+    for (const std::string& serviceName : serviceNames) {
+        sp<IContexthubVersion> hubApi = IContexthubVersion::getService(serviceName);
+        if (hubApi != nullptr) {
+            hidl_vec<V1_0::ContextHub> hubs = getHubsSync(hubApi.get());
+            for (const V1_0::ContextHub& hub : hubs) {
+                parameters.push_back(std::make_tuple(serviceName, std::to_string(hub.hubId)));
+            }
+        }
+    }
+
+    return parameters;
+}
+
+}  // namespace vts_utils
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
diff --git a/current.txt b/current.txt
index 14e709e..1dbf5ab 100644
--- a/current.txt
+++ b/current.txt
@@ -906,6 +906,7 @@
 
 # ABI preserving changes to HALs during Android T
 62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot
+f767a132ef28275294db15353f14f3876a4048770751931a77d038d4228f2cb7 android.hardware.graphics.composer@2.4::IComposerClient
 ca62a2a95d173ed323309e5e00f653ad3cceec82a6e5e4976a249cb5aafe2515 android.hardware.neuralnetworks@1.2::types
 fa76bced6b1b71c40fc706c508a9011284c57f57831cd0cf5f45653ed4ea463e android.hardware.neuralnetworks@1.3::types
 
diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp
index 3c9c29a..a73182e 100644
--- a/gnss/1.1/default/Android.bp
+++ b/gnss/1.1/default/Android.bp
@@ -27,7 +27,7 @@
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@1.0",
-        "android.hardware.gnss-V1-ndk",
+        "android.hardware.gnss-V2-ndk",
     ],
     static_libs: [
         "android.hardware.gnss@common-default-lib",
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 695246a..769e8ae 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -50,7 +50,7 @@
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@1.0",
-        "android.hardware.gnss-V1-ndk",
+        "android.hardware.gnss-V2-ndk",
     ],
     static_libs: [
         "android.hardware.gnss@common-default-lib",
diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp
index c46c735..2979f5c 100644
--- a/gnss/2.1/default/Android.bp
+++ b/gnss/2.1/default/Android.bp
@@ -44,7 +44,7 @@
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@2.0",
-        "android.hardware.gnss-V1-ndk",
+        "android.hardware.gnss-V2-ndk",
     ],
     static_libs: [
         "android.hardware.gnss@common-default-lib",
diff --git a/gnss/aidl/Android.bp b/gnss/aidl/Android.bp
index b197eae..12dd0ac 100644
--- a/gnss/aidl/Android.bp
+++ b/gnss/aidl/Android.bp
@@ -24,9 +24,27 @@
 }
 
 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"],
     stability: "vintf",
     backend: {
         java: {
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.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
new file mode 100644
index 0000000..7ef08d2
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss.visibility_control;
+@VintfStability
+interface IGnssVisibilityControl {
+  void enableNfwLocationAccess(in 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.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
new file mode 100644
index 0000000..37e1886
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible 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.visibility_control;
+@VintfStability
+interface IGnssVisibilityControlCallback {
+  void nfwNotifyCb(in android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback.NfwNotification notification);
+  boolean isInEmergencySession();
+  @Backing(type="int") @VintfStability
+  enum NfwProtocolStack {
+    CTRL_PLANE = 0,
+    SUPL = 1,
+    IMS = 10,
+    SIM = 11,
+    OTHER_PROTOCOL_STACK = 100,
+  }
+  @Backing(type="int") @VintfStability
+  enum NfwRequestor {
+    CARRIER = 0,
+    OEM = 10,
+    MODEM_CHIPSET_VENDOR = 11,
+    GNSS_CHIPSET_VENDOR = 12,
+    OTHER_CHIPSET_VENDOR = 13,
+    AUTOMOBILE_CLIENT = 20,
+    OTHER_REQUESTOR = 100,
+  }
+  @Backing(type="int") @VintfStability
+  enum NfwResponseType {
+    REJECTED = 0,
+    ACCEPTED_NO_LOCATION_PROVIDED = 1,
+    ACCEPTED_LOCATION_PROVIDED = 2,
+  }
+  @VintfStability
+  parcelable NfwNotification {
+    String proxyAppPackageName;
+    android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback.NfwProtocolStack protocolStack;
+    String otherProtocolStackName;
+    android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback.NfwRequestor requestor;
+    String requestorId;
+    android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback.NfwResponseType responseType;
+    boolean inEmergencyMode;
+    boolean isCachedLocation;
+  }
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssLocation.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssLocation.aidl
new file mode 100644
index 0000000..54c126c
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssLocation.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+parcelable GnssLocation {
+  int gnssLocationFlags;
+  double latitudeDegrees;
+  double longitudeDegrees;
+  double altitudeMeters;
+  double speedMetersPerSec;
+  double bearingDegrees;
+  double horizontalAccuracyMeters;
+  double verticalAccuracyMeters;
+  double speedAccuracyMetersPerSecond;
+  double bearingAccuracyDegrees;
+  long timestampMillis;
+  android.hardware.gnss.ElapsedRealtime elapsedRealtime;
+  const int HAS_LAT_LONG = 1;
+  const int HAS_ALTITUDE = 2;
+  const int HAS_SPEED = 4;
+  const int HAS_BEARING = 8;
+  const int HAS_HORIZONTAL_ACCURACY = 16;
+  const int HAS_VERTICAL_ACCURACY = 32;
+  const int HAS_SPEED_ACCURACY = 64;
+  const int HAS_BEARING_ACCURACY = 128;
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnss.aidl
new file mode 100644
index 0000000..f02e08c
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnss.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+interface IAGnss {
+  void setCallback(in android.hardware.gnss.IAGnssCallback callback);
+  void dataConnClosed();
+  void dataConnFailed();
+  void setServer(in android.hardware.gnss.IAGnssCallback.AGnssType type, in String hostname, in int port);
+  void dataConnOpen(in long networkHandle, in String apn, in android.hardware.gnss.IAGnss.ApnIpType apnIpType);
+  @Backing(type="int") @VintfStability
+  enum ApnIpType {
+    INVALID = 0,
+    IPV4 = 1,
+    IPV6 = 2,
+    IPV4V6 = 3,
+  }
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssCallback.aidl
new file mode 100644
index 0000000..2a46f61
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssCallback.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+interface IAGnssCallback {
+  void agnssStatusCb(in android.hardware.gnss.IAGnssCallback.AGnssType type, in android.hardware.gnss.IAGnssCallback.AGnssStatusValue status);
+  @Backing(type="int") @VintfStability
+  enum AGnssType {
+    SUPL = 1,
+    C2K = 2,
+    SUPL_EIMS = 3,
+    SUPL_IMS = 4,
+  }
+  @Backing(type="int") @VintfStability
+  enum AGnssStatusValue {
+    REQUEST_AGNSS_DATA_CONN = 1,
+    RELEASE_AGNSS_DATA_CONN = 2,
+    AGNSS_DATA_CONNECTED = 3,
+    AGNSS_DATA_CONN_DONE = 4,
+    AGNSS_DATA_CONN_FAILED = 5,
+  }
+}
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 f93b496..3477380 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
@@ -36,10 +36,16 @@
 interface IGnss {
   void setCallback(in android.hardware.gnss.IGnssCallback callback);
   void close();
-  android.hardware.gnss.IGnssPsds getExtensionPsds();
+  @nullable android.hardware.gnss.IGnssPsds getExtensionPsds();
   android.hardware.gnss.IGnssConfiguration getExtensionGnssConfiguration();
   android.hardware.gnss.IGnssMeasurementInterface getExtensionGnssMeasurement();
   android.hardware.gnss.IGnssPowerIndication getExtensionGnssPowerIndication();
+  @nullable android.hardware.gnss.IGnssBatching getExtensionGnssBatching();
+  @nullable android.hardware.gnss.IGnssGeofence getExtensionGnssGeofence();
+  @nullable android.hardware.gnss.IGnssNavigationMessageInterface getExtensionGnssNavigationMessage();
+  android.hardware.gnss.IAGnss getExtensionAGnss();
+  android.hardware.gnss.IGnssDebug getExtensionGnssDebug();
+  android.hardware.gnss.visibility_control.IGnssVisibilityControl getExtensionGnssVisibilityControl();
   const int ERROR_INVALID_ARGUMENT = 1;
   const int ERROR_ALREADY_INIT = 2;
   const int ERROR_GENERIC = 3;
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
new file mode 100644
index 0000000..492edc3
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatching.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+interface IGnssBatching {
+  void init(in android.hardware.gnss.IGnssBatchingCallback callback);
+  int getBatchSize();
+  void start(in long periodNanos, in int flags);
+  void flush();
+  void stop();
+  void cleanup();
+  const int WAKEUP_ON_FIFO_FULL = 1;
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatchingCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatchingCallback.aidl
new file mode 100644
index 0000000..427137a
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatchingCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+interface IGnssBatchingCallback {
+  void gnssLocationBatchCb(in android.hardware.gnss.GnssLocation[] locations);
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssDebug.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssDebug.aidl
new file mode 100644
index 0000000..27d9887
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssDebug.aidl
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible 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 IGnssDebug {
+  android.hardware.gnss.IGnssDebug.DebugData getDebugData();
+  @Backing(type="int") @VintfStability
+  enum SatelliteEphemerisType {
+    EPHEMERIS = 0,
+    ALMANAC_ONLY = 1,
+    NOT_AVAILABLE = 2,
+  }
+  @Backing(type="int") @VintfStability
+  enum SatelliteEphemerisSource {
+    DEMODULATED = 0,
+    SUPL_PROVIDED = 1,
+    OTHER_SERVER_PROVIDED = 2,
+    OTHER = 3,
+  }
+  @Backing(type="int") @VintfStability
+  enum SatelliteEphemerisHealth {
+    GOOD = 0,
+    BAD = 1,
+    UNKNOWN = 2,
+  }
+  @VintfStability
+  parcelable TimeDebug {
+    long timeEstimateMs;
+    float timeUncertaintyNs;
+    float frequencyUncertaintyNsPerSec;
+  }
+  @VintfStability
+  parcelable PositionDebug {
+    boolean valid;
+    double latitudeDegrees;
+    double longitudeDegrees;
+    float altitudeMeters;
+    float speedMetersPerSec;
+    float bearingDegrees;
+    double horizontalAccuracyMeters;
+    double verticalAccuracyMeters;
+    double speedAccuracyMetersPerSecond;
+    double bearingAccuracyDegrees;
+    float ageSeconds;
+  }
+  @VintfStability
+  parcelable SatelliteData {
+    int svid;
+    android.hardware.gnss.GnssConstellationType constellation;
+    android.hardware.gnss.IGnssDebug.SatelliteEphemerisType ephemerisType;
+    android.hardware.gnss.IGnssDebug.SatelliteEphemerisSource ephemerisSource;
+    android.hardware.gnss.IGnssDebug.SatelliteEphemerisHealth ephemerisHealth;
+    float ephemerisAgeSeconds;
+    boolean serverPredictionIsAvailable;
+    float serverPredictionAgeSeconds;
+  }
+  @VintfStability
+  parcelable DebugData {
+    android.hardware.gnss.IGnssDebug.PositionDebug position;
+    android.hardware.gnss.IGnssDebug.TimeDebug time;
+    List<android.hardware.gnss.IGnssDebug.SatelliteData> satelliteDataArray;
+  }
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssGeofence.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssGeofence.aidl
new file mode 100644
index 0000000..50da5bf
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssGeofence.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+interface IGnssGeofence {
+  void setCallback(in android.hardware.gnss.IGnssGeofenceCallback callback);
+  void addGeofence(in int geofenceId, in double latitudeDegrees, in double longitudeDegrees, in double radiusMeters, in int lastTransition, in int monitorTransitions, in int notificationResponsivenessMs, in int unknownTimerMs);
+  void pauseGeofence(in int geofenceId);
+  void resumeGeofence(in int geofenceId, in int monitorTransitions);
+  void removeGeofence(in int geofenceId);
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssGeofenceCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssGeofenceCallback.aidl
new file mode 100644
index 0000000..26482ea
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssGeofenceCallback.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+interface IGnssGeofenceCallback {
+  void gnssGeofenceTransitionCb(in int geofenceId, in android.hardware.gnss.GnssLocation location, in int transition, in long timestampMillis);
+  void gnssGeofenceStatusCb(in int availability, in android.hardware.gnss.GnssLocation lastLocation);
+  void gnssGeofenceAddCb(in int geofenceId, in int status);
+  void gnssGeofenceRemoveCb(in int geofenceId, in int status);
+  void gnssGeofencePauseCb(in int geofenceId, in int status);
+  void gnssGeofenceResumeCb(in int geofenceId, in int status);
+  const int ENTERED = 1;
+  const int EXITED = 2;
+  const int UNCERTAIN = 4;
+  const int UNAVAILABLE = 1;
+  const int AVAILABLE = 2;
+  const int OPERATION_SUCCESS = 0;
+  const int ERROR_TOO_MANY_GEOFENCES = -100;
+  const int ERROR_ID_EXISTS = -101;
+  const int ERROR_ID_UNKNOWN = -102;
+  const int ERROR_INVALID_TRANSITION = -103;
+  const int ERROR_GENERIC = -149;
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
new file mode 100644
index 0000000..d513c15
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+interface IGnssNavigationMessageCallback {
+  void gnssNavigationMessageCb(in android.hardware.gnss.IGnssNavigationMessageCallback.GnssNavigationMessage message);
+  @VintfStability
+  parcelable GnssNavigationMessage {
+    int svid;
+    android.hardware.gnss.IGnssNavigationMessageCallback.GnssNavigationMessage.GnssNavigationMessageType type;
+    int status;
+    int messageId;
+    int submessageId;
+    byte[] data;
+    const int STATUS_PARITY_PASSED = 1;
+    const int STATUS_PARITY_REBUILT = 2;
+    const int STATUS_UNKNOWN = 0;
+    @Backing(type="int") @VintfStability
+    enum GnssNavigationMessageType {
+      UNKNOWN = 0,
+      GPS_L1CA = 257,
+      GPS_L2CNAV = 258,
+      GPS_L5CNAV = 259,
+      SBS = 513,
+      GPS_CNAV2 = 260,
+      GLO_L1CA = 769,
+      QZS_L1CA = 1025,
+      BDS_D1 = 1281,
+      BDS_D2 = 1282,
+      BDS_CNAV1 = 1283,
+      BDS_CNAV2 = 1284,
+      GAL_I = 1537,
+      GAL_F = 1538,
+      IRN_L5CA = 1793,
+    }
+  }
+}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageInterface.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageInterface.aidl
new file mode 100644
index 0000000..196e9b9
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageInterface.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gnss;
+@VintfStability
+interface IGnssNavigationMessageInterface {
+  void setCallback(in android.hardware.gnss.IGnssNavigationMessageCallback callback);
+  void close();
+}
diff --git a/gnss/aidl/android/hardware/gnss/GnssLocation.aidl b/gnss/aidl/android/hardware/gnss/GnssLocation.aidl
new file mode 100644
index 0000000..25aea4d
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/GnssLocation.aidl
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.ElapsedRealtime;
+
+/** Represents a location. */
+@VintfStability
+parcelable GnssLocation {
+    /** Bit mask to indicate GnssLocation has valid latitude and longitude. */
+    const int HAS_LAT_LONG = 0x0001;
+    /** Bit mask to indicate GnssLocation has valid altitude. */
+    const int HAS_ALTITUDE = 0x0002;
+    /** Bit mask to indicate GnssLocation has valid speed. */
+    const int HAS_SPEED = 0x0004;
+    /** Bit mask to indicate GnssLocation has valid bearing. */
+    const int HAS_BEARING = 0x0008;
+    /** Bit mask to indicate GnssLocation has valid horizontal accuracy. */
+    const int HAS_HORIZONTAL_ACCURACY = 0x0010;
+    /** Bit mask to indicate GnssLocation has valid vertical accuracy. */
+    const int HAS_VERTICAL_ACCURACY = 0x0020;
+    /** Bit mask to indicate GnssLocation has valid speed accuracy. */
+    const int HAS_SPEED_ACCURACY = 0x0040;
+    /** Bit mask to indicate GnssLocation has valid bearing accuracy. */
+    const int HAS_BEARING_ACCURACY = 0x0080;
+
+    /** A bit field of flags indicating the validity of the fields in this GnssLocation. */
+    int gnssLocationFlags;
+
+    /** Represents latitude in degrees. */
+    double latitudeDegrees;
+
+    /** Represents longitude in degrees. */
+    double longitudeDegrees;
+
+    /** Represents altitude in meters above the WGS 84 reference ellipsoid. */
+    double altitudeMeters;
+
+    /** Represents speed in meters per second. */
+    double speedMetersPerSec;
+
+    /** Represents heading in degrees. */
+    double bearingDegrees;
+
+    /**
+     * Represents expected horizontal position accuracy, radial, in meters (68% confidence).
+     */
+    double horizontalAccuracyMeters;
+
+    /**
+     * Represents expected vertical position accuracy in meters (68% confidence).
+     */
+    double verticalAccuracyMeters;
+
+    /**
+     * Represents expected speed accuracy in meter per seconds (68% confidence).
+     */
+    double speedAccuracyMetersPerSecond;
+
+    /**
+     * Represents expected bearing accuracy in degrees (68% confidence).
+     */
+    double bearingAccuracyDegrees;
+
+    /** Timestamp for the location fix in milliseconds since January 1, 1970. */
+    long timestampMillis;
+
+    /**
+     * Timing information of the GNSS location synchronized with SystemClock.elapsedRealtimeNanos()
+     * clock.
+     *
+     * This clock information can be obtained from SystemClock.elapsedRealtimeNanos(), when the GNSS
+     * is attached straight to the AP/SOC. When it is attached to a separate module the timestamp
+     * needs to be estimated by syncing the notion of time via PTP or some other mechanism.
+     */
+    ElapsedRealtime elapsedRealtime;
+}
diff --git a/gnss/aidl/android/hardware/gnss/IAGnss.aidl b/gnss/aidl/android/hardware/gnss/IAGnss.aidl
new file mode 100644
index 0000000..3e256e2
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IAGnss.aidl
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.IAGnssCallback;
+import android.hardware.gnss.IAGnssCallback.AGnssType;
+
+/** Extended interface for Assisted GNSS support. */
+@VintfStability
+interface IAGnss {
+    /** Access point name IP type */
+    @VintfStability
+    @Backing(type="int")
+    enum ApnIpType {
+        INVALID = 0,
+        IPV4 = 1,
+        IPV6 = 2,
+        IPV4V6 = 3,
+    }
+
+    /**
+     * Opens the AGNSS interface and provides the callback routines to the
+     * implementation of this interface.
+     *
+     * If setCallback is not called, this interface will not respond to any
+     * other method calls.
+     *
+     * @param callback Handle to the AGNSS status callback interface.
+     */
+    void setCallback(in IAGnssCallback callback);
+
+    /**
+     * Notifies that the AGNSS data connection has been closed.
+     */
+    void dataConnClosed();
+
+    /**
+     * Notifies that a data connection is not available for AGNSS.
+     */
+    void dataConnFailed();
+
+    /**
+     * Sets the hostname and port for the AGNSS server.
+     *
+     * @param type Specifies if SUPL or C2K.
+     * @param hostname Hostname of the AGNSS server.
+     * @param port Port number associated with the server.
+     */
+    void setServer(in AGnssType type, in String hostname, in int port);
+
+    /**
+     * Notifies GNSS that a data connection is available and sets the network handle,
+     * name of the APN, and its IP type to be used for SUPL connections.
+     *
+     * The HAL implementation must use the network handle to set the network for the
+     * SUPL connection sockets using the android_setsocknetwork function. This will ensure
+     * that there is a network path to the SUPL server. The network handle can also be used
+     * to get the IP address of SUPL FQDN using the android_getaddrinfofornetwork() function.
+     *
+     * @param networkHandle Handle representing the network for use with the NDK API.
+     * @param apn Access Point Name (follows regular APN naming convention).
+     * @param apnIpType Specifies IP type of APN.
+     */
+    void dataConnOpen(in long networkHandle, in String apn, in ApnIpType apnIpType);
+}
diff --git a/gnss/aidl/android/hardware/gnss/IAGnssCallback.aidl b/gnss/aidl/android/hardware/gnss/IAGnssCallback.aidl
new file mode 100644
index 0000000..7c25937
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IAGnssCallback.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+/** Callback structure for the AGNSS interface. */
+@VintfStability
+interface IAGnssCallback {
+    /** AGNSS service type */
+    @VintfStability
+    @Backing(type="int")
+    enum AGnssType {
+        SUPL = 1,
+        C2K = 2,
+        SUPL_EIMS = 3,
+        SUPL_IMS = 4,
+    }
+
+    /** AGNSS status value */
+    @VintfStability
+    @Backing(type="int")
+    enum AGnssStatusValue {
+        /** GNSS requests data connection for AGNSS. */
+        REQUEST_AGNSS_DATA_CONN = 1,
+
+        /** GNSS releases the AGNSS data connection. */
+        RELEASE_AGNSS_DATA_CONN = 2,
+
+        /** AGNSS data connection initiated */
+        AGNSS_DATA_CONNECTED = 3,
+
+        /** AGNSS data connection completed */
+        AGNSS_DATA_CONN_DONE = 4,
+
+        /** AGNSS data connection failed */
+        AGNSS_DATA_CONN_FAILED = 5,
+    }
+
+    /**
+     * Callback with AGNSS status information.
+     *
+     * The GNSS HAL implementation must use this method to request the framework to setup
+     * network connection for the specified AGNSS service and to update the connection
+     * status so that the framework can release the resources.
+     *
+     * @param type Type of AGNSS service.
+     * @parama status Status of the data connection.
+     */
+    void agnssStatusCb(in AGnssType type, in AGnssStatusValue status);
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
index f99b512..1351f59 100644
--- a/gnss/aidl/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -16,20 +16,25 @@
 
 package android.hardware.gnss;
 
+import android.hardware.gnss.IAGnss;
+import android.hardware.gnss.IGnssBatching;
 import android.hardware.gnss.IGnssCallback;
 import android.hardware.gnss.IGnssConfiguration;
+import android.hardware.gnss.IGnssDebug;
+import android.hardware.gnss.IGnssGeofence;
 import android.hardware.gnss.IGnssMeasurementInterface;
+import android.hardware.gnss.IGnssNavigationMessageInterface;
 import android.hardware.gnss.IGnssPowerIndication;
 import android.hardware.gnss.IGnssPsds;
+import android.hardware.gnss.visibility_control.IGnssVisibilityControl;
 
 /**
  * Represents the standard GNSS (Global Navigation Satellite System) interface.
  */
 @VintfStability
 interface IGnss {
-
     /**
-     * All GNSS Binder calls may return a ServiceSpecificException with the following error
+     * All GNSS binder calls may return a ServiceSpecificException with the following error
      * codes.
      */
     const int ERROR_INVALID_ARGUMENT = 1;
@@ -73,27 +78,25 @@
     /**
      * This method returns the IGnssPsds interface.
      *
-     * This method must return non-null.
-     *
-     * @return Handle to the IGnssPsds interface.
+     * @return The IGnssPsds interface.
      */
-    IGnssPsds getExtensionPsds();
+    @nullable IGnssPsds getExtensionPsds();
 
     /**
      * This method returns the IGnssConfiguration interface.
      *
      * This method must return non-null.
      *
-     * @return Handle to the IGnssConfiguration interface.
+     * @return The IGnssConfiguration interface.
      */
     IGnssConfiguration getExtensionGnssConfiguration();
 
     /**
-     * This methods returns the IGnssMeasurementInterface interface.
+     * This method returns the IGnssMeasurementInterface interface.
      *
      * This method must return non-null.
      *
-     * @return Handle to the IGnssMeasurementInterface interface.
+     * @return The IGnssMeasurementInterface interface.
      */
     IGnssMeasurementInterface getExtensionGnssMeasurement();
 
@@ -102,7 +105,51 @@
      *
      * This method must return non-null.
      *
-     * @return Handle to the IGnssPowerIndication interface.
+     * @return The IGnssPowerIndication interface.
      */
     IGnssPowerIndication getExtensionGnssPowerIndication();
+
+    /**
+     * This method returns the IGnssBatching interface.
+     *
+     * @return The IGnssBatching interface.
+     */
+    @nullable IGnssBatching getExtensionGnssBatching();
+
+    /**
+     * This method returns the IGnssGeofence interface.
+     *
+     * @return The IGnssGeofence interface.
+     */
+    @nullable IGnssGeofence getExtensionGnssGeofence();
+
+    /**
+     * This method returns the IGnssNavigationMessageInterface.
+     *
+     * @return The IGnssNavigationMessageInterface.
+     */
+    @nullable IGnssNavigationMessageInterface getExtensionGnssNavigationMessage();
+
+    /**
+     * This method returns the IAGnss interface.
+     *
+     * @return The IAGnss interface.
+     */
+    IAGnss getExtensionAGnss();
+
+    /**
+     * This method returns the IGnssDebug interface.
+     *
+     * This method must return non-null.
+     *
+     * @return Handle to the IGnssDebug interface.
+     */
+    IGnssDebug getExtensionGnssDebug();
+
+    /**
+     * This method returns the IGnssVisibilityControl.
+     *
+     * @return Handle to the IGnssVisibilityControl.
+     */
+    IGnssVisibilityControl getExtensionGnssVisibilityControl();
 }
diff --git a/gnss/aidl/android/hardware/gnss/IGnssBatching.aidl b/gnss/aidl/android/hardware/gnss/IGnssBatching.aidl
new file mode 100644
index 0000000..0d48ee1
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssBatching.aidl
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.IGnssBatchingCallback;
+
+/**
+ * Extended interface for GNSS Batching support.
+ *
+ * If this interface is supported, this batching request must be able to run in parallel with, or
+ * without, non-batched location requested by the IGnss start() & stop() - i.e. both requests must
+ * be handled independently, and not interfere with each other.
+ *
+ * For example, if a 1Hz continuous output is underway on the IGnssCallback, due to an IGnss start()
+ * operation, and then a IGnssBatching start() is called for a location every 10 seconds, the newly
+ * added batching request must not disrupt the 1Hz continuous location output on the IGnssCallback.
+ *
+ * As with GNSS Location outputs, source of location must be GNSS satellite measurements, optionally
+ * using interial and baro sensors to improve relative motion filtering. No additional absolute
+ * positioning information, such as WiFi derived location, may be mixed with the GNSS information.
+ */
+@VintfStability
+interface IGnssBatching {
+    /**
+     * Bit mask indicating batching supports wake up and flush when FIFO is full.
+     *
+     * If this flag is set, the hardware implementation must wake up the application processor when
+     * the FIFO is full, and call IGnssBatchingCallback to return the locations.
+     *
+     * If the flag is not set, the hardware implementation must drop the oldest data when the FIFO
+     * is full.
+     */
+    const int WAKEUP_ON_FIFO_FULL = 0x01;
+
+    /**
+     * Open the interface and provides the callback routines to the implementation of this
+     * interface.
+     *
+     * @param callback Callback interface for IGnssBatching.
+     */
+    void init(in IGnssBatchingCallback callback);
+
+    /**
+     * Return the batch size (in number of GnssLocation objects) available in this hardware
+     * implementation.
+     *
+     * If the available size is variable, for example, based on other operations consuming memory,
+     * this is the minimum size guaranteed to be available for batching operations.
+     *
+     * This may, for example, be used by the client, to decide on the batching interval and whether
+     * the AP should be woken up or not.
+     *
+     * @return the number of location objects supported per batch
+     */
+    int getBatchSize();
+
+    /**
+     * Start batching locations. This API is primarily used when the AP is asleep and the device can
+     * batch locations in the hardware.
+     *
+     * The implementation must invoke IGnssBatchingCallback, provided in init(), to return the
+     * location.
+     *
+     * When the buffer is full and WAKEUP_ON_FIFO_FULL is used, IGnssBatchingCallback must be called
+     * to return the locations.
+     *
+     * When the buffer is full and WAKEUP_ON_FIFO_FULL is not set, the oldest location object is
+     * dropped. In this case the AP must not be woken up. The AP would then generally be responsible
+     * 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
+     */
+    void start(in long periodNanos, in int flags);
+
+    /**
+     * Retrieve all batched locations currently stored.
+     *
+     * The implementation must invoke IGnssBatchingCallback, provided in init(), to return the
+     * location.
+     *
+     * IGnssBatchingCallback must be called in response, even if there are no locations to flush
+     * (in which case the Location vector must be empty).
+     *
+     * Subsequent calls to flush must not return any of the locations returned in this call.
+     */
+    void flush();
+
+    /**
+     * Stop batching.
+     */
+    void stop();
+
+    /**
+     * Closes the interface. If any batch operations are in progress, they must be stopped.  If any
+     * locations are in the hardware batch, they must be deleted (and not sent via callback.)
+     *
+     * init() may be called again, after this, if the interface is to be restored
+     */
+    void cleanup();
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssBatchingCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssBatchingCallback.aidl
new file mode 100644
index 0000000..b1bfc57
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssBatchingCallback.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.GnssLocation;
+
+/** The callback interface to report batched GNSS locations from the HAL. */
+@VintfStability
+interface IGnssBatchingCallback {
+    /**
+     * Called when a batch of locations is output, by various means, including
+     * a flush request, as well as the buffer becoming full (if appropriate option
+     * is set.)
+     *
+     * All locations returned by this callback must be cleared from the hardware
+     * buffer, such the sequential calls of this callback do not return any
+     * redundant locations.  (Same lat/lon, at a new time, is acceptable.)
+     *
+     * @param locations A list of GNSS Locations
+     */
+    void gnssLocationBatchCb(in GnssLocation[] locations);
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssDebug.aidl b/gnss/aidl/android/hardware/gnss/IGnssDebug.aidl
new file mode 100644
index 0000000..475a4a3
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssDebug.aidl
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.GnssConstellationType;
+
+/**
+ * Extended interface for GNSS Debug support
+ *
+ * This information is used for debugging purpose, e.g., shown in a bugreport to
+ * describe the chipset states including time, position, and satellite data.
+ */
+@VintfStability
+interface IGnssDebug {
+    /** Satellite's ephemeris type */
+    @VintfStability
+    @Backing(type="int")
+    enum SatelliteEphemerisType {
+        EPHEMERIS = 0,
+        ALMANAC_ONLY = 1,
+        NOT_AVAILABLE = 2,
+    }
+
+    /** Satellite's ephemeris source */
+    @VintfStability
+    @Backing(type="int")
+    enum SatelliteEphemerisSource {
+        DEMODULATED = 0,
+        SUPL_PROVIDED = 1,
+        OTHER_SERVER_PROVIDED = 2,
+        OTHER = 3,
+    }
+
+    /** Satellite's ephemeris health */
+    @VintfStability
+    @Backing(type="int")
+    enum SatelliteEphemerisHealth {
+        GOOD = 0,
+        BAD = 1,
+        UNKNOWN = 2,
+    }
+
+    /**
+     * Provides the current best known UTC time estimate.
+     * If no fresh information is available, e.g. after a delete all,
+     * then whatever the effective defaults are on the device must be
+     * provided (e.g. Jan. 1, 2017, with an uncertainty of 5 years) expressed
+     * in the specified units.
+     */
+    @VintfStability
+    parcelable TimeDebug {
+        /** UTC time estimate in milliseconds. */
+        long timeEstimateMs;
+
+        /** 68% time error estimate in nanoseconds. */
+        float timeUncertaintyNs;
+
+        /**
+         * 68% error estimate in local clock drift,
+         * in nanoseconds per second (also known as parts per billion - ppb.)
+         */
+        float frequencyUncertaintyNsPerSec;
+    }
+
+    @VintfStability
+    parcelable PositionDebug {
+        /**
+         * Validity of the data in this struct. False only if no
+         * latitude/longitude information is known.
+         */
+        boolean valid;
+
+        /** Latitude expressed in degrees */
+        double latitudeDegrees;
+
+        /** Longitude expressed in degrees */
+        double longitudeDegrees;
+
+        /** Altitude above ellipsoid expressed in meters */
+        float altitudeMeters;
+
+        /** Represents horizontal speed in meters per second. */
+        float speedMetersPerSec;
+
+        /** Represents heading in degrees. */
+        float bearingDegrees;
+
+        /**
+         * Estimated horizontal accuracy of position expressed in meters,
+         * radial, 68% confidence.
+         */
+        double horizontalAccuracyMeters;
+
+        /**
+         * Estimated vertical accuracy of position expressed in meters, with
+         * 68% confidence.
+         */
+        double verticalAccuracyMeters;
+
+        /**
+         * Estimated speed accuracy in meters per second with 68% confidence.
+         */
+        double speedAccuracyMetersPerSecond;
+
+        /**
+         * Estimated bearing accuracy degrees with 68% confidence.
+         */
+        double bearingAccuracyDegrees;
+
+        /**
+         * Time duration before this report that this position information was
+         * valid.  This can, for example, be a previous injected location with
+         * an age potentially thousands of seconds old, or
+         * extrapolated to the current time (with appropriately increased
+         * accuracy estimates), with a (near) zero age.
+         */
+        float ageSeconds;
+    }
+
+    @VintfStability
+    parcelable SatelliteData {
+        /** Satellite vehicle ID number */
+        int svid;
+
+        /** Defines the constellation type of the given SV. */
+        GnssConstellationType constellation;
+
+        /**
+         * Defines the standard broadcast ephemeris or almanac availability for
+         * the satellite.  To report status of predicted orbit and clock
+         * information, see the serverPrediction fields below.
+         */
+        SatelliteEphemerisType ephemerisType;
+
+        /** Defines the ephemeris source of the satellite. */
+        SatelliteEphemerisSource ephemerisSource;
+
+        /**
+         * Defines whether the satellite is known healthy
+         * (safe for use in location calculation.)
+         */
+        SatelliteEphemerisHealth ephemerisHealth;
+
+        /**
+         * Time duration from this report (current time), minus the
+         * effective time of the ephemeris source (e.g. TOE, TOA.)
+         * Set to 0 when ephemerisType is NOT_AVAILABLE.
+         */
+        float ephemerisAgeSeconds;
+
+        /**
+         * True if a server has provided a predicted orbit and clock model for
+         * this satellite.
+         */
+        boolean serverPredictionIsAvailable;
+
+        /**
+         * Time duration from this report (current time) minus the time of the
+         * start of the server predicted information.  For example, a 1 day
+         * old prediction would be reported as 86400 seconds here.
+         */
+        float serverPredictionAgeSeconds;
+    }
+
+    /**
+     * Provides a set of debug information that is filled by the GNSS chipset
+     * when the method getDebugData() is invoked.
+     */
+    @VintfStability
+    parcelable DebugData {
+        /** Current best known position. */
+        PositionDebug position;
+
+        /** Current best know time estimate */
+        TimeDebug time;
+
+        /**
+         * Provides a list of the available satellite data, for all
+         * satellites and constellations the device can track,
+         * including GnssConstellationType UNKNOWN.
+         */
+        List<SatelliteData> satelliteDataArray;
+    }
+
+    /**
+     * This methods requests position, time and satellite ephemeris debug information
+     * from the HAL.
+     *
+     * @return ret debugData information from GNSS Hal that contains the current best
+     * known position, best known time estimate and a complete list of
+     * constellations that the device can track.
+     */
+    DebugData getDebugData();
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssGeofence.aidl b/gnss/aidl/android/hardware/gnss/IGnssGeofence.aidl
new file mode 100644
index 0000000..bb4ff93
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssGeofence.aidl
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.IGnssGeofenceCallback;
+
+/** Extended interface for GNSS Geofence support. */
+@VintfStability
+interface IGnssGeofence {
+    /**
+     * Opens the geofence interface and provides the callback routines to the HAL.
+     *
+     * @param callback Handle to the IGnssGeofenceCallback interface.
+     */
+    void setCallback(in IGnssGeofenceCallback callback);
+
+    /**
+     * Add a geofence area. This api currently supports circular geofences.
+     *
+     * @param geofenceId The id for the geofence. If a geofence with this id already exists, an
+     * error value (ERROR_ID_EXISTS) must be returned.
+     * @param latitudeDegrees The latitude(in degrees) for the geofence lastTransition.
+     * @param longitudeDegrees The longitude(in degrees) for the geofence lastTransition.
+     * @param radiusMeters The radius(in meters) for the geofence lastTransition.
+     * @param lastTransition The current state of the geofence. It can be one of the transition
+     * states (ENTERED, EXITED, UNCERTAIN) as defined in IGnssGeofenceCallback. For example, if
+     * the system already knows that the user is inside the geofence, this will be set to ENTERED.
+     * In most cases, it will be UNCERTAIN.
+     * @param monitorTransitions A bitfield of ENTERED, EXITED and UNCERTAIN. It represents which
+     * transitions to monitor.
+     * @param notificationResponsivenessMs - Defines the best-effort description of how soon must
+     * the callback be called when the transition associated with the Geofence is triggered. For
+     * instance, if set to 1000 milliseconds with ENTERED, the callback must be called 1000
+     * milliseconds within entering the geofence. This parameter is defined in milliseconds.
+     * NOTE: This is not to be confused with the rate that the GNSS is polled at. It is acceptable
+     * to dynamically vary the rate of sampling the GNSS for power-saving reasons; thus the rate of
+     * sampling may be faster or slower than this.
+     * @param unknownTimerMs - The time limit in millisecondsafter which the UNCERTAIN transition
+     * must be triggered.
+     */
+    void addGeofence(in int geofenceId, in double latitudeDegrees, in double longitudeDegrees,
+            in double radiusMeters, in int lastTransition, in int monitorTransitions,
+            in int notificationResponsivenessMs, in int unknownTimerMs);
+
+    /**
+     * Pause monitoring a particular geofence.
+     *
+     * @param geofenceId The id for the geofence.
+     */
+    void pauseGeofence(in int geofenceId);
+
+    /**
+     * Resume monitoring a particular geofence.
+     *
+     * @param geofenceId - The id for the geofence.
+     * @param monitorTransitions Specifies which transitions to monitor. It can be a bitwise OR of
+     * ENTERED, EXITED and UNCERTAIN. This supersedes the value associated provided in the
+     * addGeofence call.
+     */
+    void resumeGeofence(in int geofenceId, in int monitorTransitions);
+
+    /**
+     * Remove a geofence area. After the function returns, no notifications must be sent.
+     *
+     * @param geofenceId The id of the geofence.
+     */
+    void removeGeofence(in int geofenceId);
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssGeofenceCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssGeofenceCallback.aidl
new file mode 100644
index 0000000..c176965
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssGeofenceCallback.aidl
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.GnssLocation;
+
+/**
+ * The callback interface to report GNSS geofence events from the HAL.
+ *
+ * There are 3 states associated with a Geofence: Inside, Outside, Unknown.
+ * There are 3 transitions: ENTERED, EXITED, UNCERTAIN.
+ *
+ * An example state diagram with confidence level: 95% and Unknown time limit
+ * set as 30 secs is shown below. (confidence level and Unknown time limit are
+ * explained latter).
+ *                         ____________________________
+ *                        |       Unknown (30 secs)   |
+ *                         """"""""""""""""""""""""""""
+ *                            ^ |                  |  ^
+ *                   UNCERTAIN| |ENTERED     EXITED|  |UNCERTAIN
+ *                            | v                  v  |
+ *                        ________    EXITED     _________
+ *                       | Inside | -----------> | Outside |
+ *                       |        | <----------- |         |
+ *                        """"""""    ENTERED    """""""""
+ *
+ * Inside state: We are 95% confident that the user is inside the geofence.
+ * Outside state: We are 95% confident that the user is outside the geofence
+ * Unknown state: Rest of the time.
+ *
+ * The Unknown state is better explained with an example:
+ *
+ *                            __________
+ *                           |         c|
+ *                           |  ___     |    _______
+ *                           |  |a|     |   |   b   |
+ *                           |  """     |    """""""
+ *                           |          |
+ *                            """"""""""
+ * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy
+ * circle reported by the GNSS subsystem. Now with regard to "b", the system is
+ * confident that the user is outside. But with regard to "a" is not confident
+ * whether it is inside or outside the geofence. If the accuracy remains the
+ * same for a sufficient period of time, the UNCERTAIN transition must be
+ * triggered with the state set to Unknown. If the accuracy improves later, an
+ * appropriate transition must be triggered.  This "sufficient period of time"
+ * is defined by the parameter in the addGeofenceArea API.
+ * In other words, Unknown state can be interpreted as a state in which the
+ * GNSS subsystem isn't confident enough that the user is either inside or
+ * outside the Geofence. It moves to Unknown state only after the expiry of the
+ * timeout.
+ *
+ * The geofence callback needs to be triggered for the ENTERED and EXITED
+ * transitions, when the GNSS system is confident that the user has entered
+ * (Inside state) or exited (Outside state) the Geofence. An implementation
+ * which uses a value of 95% as the confidence is recommended. The callback
+ * must be triggered only for the transitions requested by the
+ * addGeofenceArea method.
+ *
+ * Even though the diagram and explanation talks about states and transitions,
+ * the callee is only interested in the transitions. The states are mentioned
+ * here for illustrative purposes.
+ *
+ * Startup Scenario: When the device boots up, if an application adds geofences,
+ * and then we get an accurate GNSS location fix, it needs to trigger the
+ * appropriate (ENTERED or EXITED) transition for every Geofence it knows about.
+ * By default, all the Geofences will be in the Unknown state.
+ *
+ * When the GNSS system is unavailable, gnssGeofenceStatusCb must be
+ * called to inform the upper layers of the same. Similarly, when it becomes
+ * available the callback must be called. This is a global state while the
+ * UNKNOWN transition described above is per geofence.
+ *
+ * An important aspect to note is that users of this API (framework), will use
+ * other subsystems like wifi, sensors, cell to handle Unknown case and
+ * hopefully provide a definitive state transition to the third party
+ * application. GNSS Geofence will just be a signal indicating what the GNSS
+ * subsystem knows about the Geofence.
+ */
+@VintfStability
+interface IGnssGeofenceCallback {
+    // Geofence transition status
+    const int ENTERED = 1 << 0;
+    const int EXITED = 1 << 1;
+    const int UNCERTAIN = 1 << 2;
+
+    // Geofence availability status
+    const int UNAVAILABLE = 1 << 0;
+    const int AVAILABLE = 1 << 1;
+
+    // Geofence operation status
+    const int OPERATION_SUCCESS = 0;
+    const int ERROR_TOO_MANY_GEOFENCES = -100;
+    const int ERROR_ID_EXISTS = -101;
+    const int ERROR_ID_UNKNOWN = -102;
+    const int ERROR_INVALID_TRANSITION = -103;
+    const int ERROR_GENERIC = -149;
+
+    /**
+     * The callback associated with the geofence transition.
+     *
+     * The callback must only be called when the caller is interested in that particular transition.
+     * For instance, if the caller is interested only in ENTERED transition, then the callback must
+     * not be called with the EXITED transition.
+     *
+     * IMPORTANT: If a transition is triggered resulting in this callback, the GNSS subsystem will
+     * wake up the application processor, if it is in suspend state.
+     *
+     * @param geofenceId The id associated with the addGeofenceArea.
+     * @param location The current GNSS location.
+     * @param transition Can be one of ENTERED, EXITED or UNCERTAIN.
+     * @param timestamp Timestamp (in UTC milliseconds) when the transition was detected.
+     */
+    void gnssGeofenceTransitionCb(in int geofenceId, in GnssLocation location, in int transition,
+            in long timestampMillis);
+
+    /**
+     * The callback associated with the availability of the GNSS system for geofencing monitoring.
+     * If the GNSS system determines that it cannot monitor geofences because of lack of reliability
+     * or unavailability of the GNSS signals, it will call this callback with UNAVAILABLE parameter.
+     *
+     * @param status - UNAVAILABLE or AVAILABLE.
+     * @param lastLocation - Last known location.
+     */
+    void gnssGeofenceStatusCb(in int availability, in GnssLocation lastLocation);
+
+    /**
+     * The callback associated with the addGeofence call.
+     *
+     * @param geofenceId Id of the geofence.
+     * @param status Returns OPERATION_SUCCESS if the geofence add was successful,
+     *               returns ERROR_TOO_MANY_GEOFENCES if the geofence limit has been reached,
+     *               returns ERROR_ID_EXISTS if geofence with id already exists,
+     *               returns ERROR_INVALID_TRANSITION if the monitorTransition contains an invalid
+     *               transition, and
+     *               returns ERROR_GENERIC for other errors.
+     */
+    void gnssGeofenceAddCb(in int geofenceId, in int status);
+
+    /**
+     * The callback associated with the removeGeofence call.
+     *
+     * @param geofenceId Id of the geofence.
+     * @param status Returns OPERATION_SUCCESS if successful,
+     *               returns ERROR_ID_UNKNOWN for invalid id and
+     *               returns ERROR_GENERIC for others.
+     */
+    void gnssGeofenceRemoveCb(in int geofenceId, in int status);
+
+    /**
+     * The callback associated with the pauseGeofence call.
+     *
+     * @param geofenceId Id of the geofence.
+     * @param status Returns OPERATION_SUCCESS if success,
+     *               returns ERROR_ID_UNKNOWN for invalid id,
+     *               returns ERROR_INVALID_TRANSITION when monitorTransitions is invalid, and
+     *               returns ERROR_GENERIC for other err errors.
+     */
+    void gnssGeofencePauseCb(in int geofenceId, in int status);
+
+    /**
+     * The callback associated with the resumeGeofence call.
+     *
+     * @param geofenceId - Id of the geofence.
+     * @param status Returns OPERATION_SUCCESS if successful,
+     *               returns ERROR_ID_UNKNOWN for invalid id, and
+     *               returns ERROR_GENERIC for others.
+     */
+    void gnssGeofenceResumeCb(in int geofenceId, in int status);
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssNavigationMessageCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
new file mode 100644
index 0000000..0fdfaf8
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
@@ -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.
+ */
+
+package android.hardware.gnss;
+
+/** Represents a GNSS navigation message (or a fragment of it). */
+@VintfStability
+interface IGnssNavigationMessageCallback {
+    /**
+     * Represents a reading of GNSS measurements. For devices launched in Android Q or newer, it is
+     * mandatory that these be provided, on request, when the GNSS receiver is searching/tracking
+     * signals.
+     *
+     * - Reporting of GNSS constellation measurements is mandatory.
+     * - Reporting of all tracked constellations are encouraged.
+     */
+    @VintfStability
+    parcelable GnssNavigationMessage {
+        /**
+         * Status of Navigation Message
+         *
+         * When a message is received properly without any parity error in its
+         * navigation words, the status must be set to PARITY_PASSED.
+         *
+         * If a message is received with words that failed a parity check, but the GNSS
+         * receiver has corrected those words, the status must be set to PARITY_REBUILT.
+         *
+         * Do not send any navigation message that contains words with parity errors
+         * that cannot be corrected.
+         */
+        const int STATUS_PARITY_PASSED = (1 << 0);
+        const int STATUS_PARITY_REBUILT = (1 << 1);
+        const int STATUS_UNKNOWN = 0;
+
+        /**
+         * Enumeration of available values to indicate the GNSS Navigation message
+         * types.
+         *
+         * For convenience, first byte is the GnssConstellationType on which that signal
+         * is typically transmitted.
+         */
+        @VintfStability
+        @Backing(type="int")
+        enum GnssNavigationMessageType {
+            UNKNOWN = 0,
+
+            /** GPS L1 C/A message contained in the structure.  */
+            GPS_L1CA = 0x0101,
+
+            /** GPS L2-CNAV message contained in the structure. */
+            GPS_L2CNAV = 0x0102,
+
+            /** GPS L5-CNAV message contained in the structure. */
+            GPS_L5CNAV = 0x0103,
+
+            /* SBAS message contained in the structure. */
+            SBS = 0x0201,
+
+            /** GPS CNAV-2 message contained in the structure. */
+            GPS_CNAV2 = 0x0104,
+
+            /** Glonass L1 CA message contained in the structure. */
+            GLO_L1CA = 0x0301,
+
+            /** QZSS L1 C/A message contained in the structure. */
+            QZS_L1CA = 0x0401,
+
+            /** Beidou D1 message contained in the structure. */
+            BDS_D1 = 0x0501,
+
+            /** Beidou D2 message contained in the structure. */
+            BDS_D2 = 0x0502,
+
+            /** Beidou CNAV1 message contained in the structure. */
+            BDS_CNAV1 = 0x0503,
+
+            /** Beidou CNAV2 message contained in the structure. */
+            BDS_CNAV2 = 0x0504,
+
+            /** Galileo I/NAV message contained in the structure. */
+            GAL_I = 0x0601,
+
+            /** Galileo F/NAV message contained in the structure. */
+            GAL_F = 0x0602,
+
+            /** IRNSS L5 C/A message contained in the structure. */
+            IRN_L5CA = 0x0701,
+        }
+
+        /**
+         * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+         *
+         * This is a mandatory value.
+         */
+        int svid;
+
+        /**
+         * The type of message contained in the structure.
+         *
+         * This is a mandatory value.
+         */
+        GnssNavigationMessageType type;
+
+        /**
+         * The status of the received navigation message.
+         *
+         * It is a bitfield of constants with prefix "STATUS_" defined in this structure.
+         *
+         * No need to send any navigation message that contains words with parity
+         * errors that cannot be corrected.
+         */
+        int status;
+
+        /**
+         * Message identifier. It provides an index so the complete Navigation
+         * Message can be assembled.
+         *
+         * - For GNSS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+         *   id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+         *   does not contain a 'frame id' and this value can be set to -1.)
+         *
+         * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+         *
+         * - For BeiDou D1, this refers to the frame number in the range of 1-24
+         *
+         * - For Beidou D2, this refers to the frame number, in the range of 1-120
+         *
+         * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+         *   number, in the range of 1-12
+         *
+         * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+         *   number in the range of 1-24
+         *
+         * - For SBAS and Beidou CNAV2, this is unused and can be set to -1.
+         *
+         * - For QZSS L1 C/A subframe 4 and 5, this value corresponds to the 'frame id' of the
+         *   navigation message, in the range of 1-25. (Subframe 1, 2, 3 does not contain a 'frame
+         *   id' and this value can be set to -1.)
+         *
+         * - For Beidou CNAV1 this refers to the page type number in the range of 1-63.
+         *
+         * - For IRNSS L5 C/A subframe 3 and 4, this value corresponds to the Message Id of the
+         *   navigation message, in the range of 1-63. (Subframe 1 and 2 does not contain a message
+         *   type id and this value can be set to -1.)
+         */
+        int messageId;
+
+        /**
+         * Sub-message identifier. If required by the message 'type', this value contains a
+         * sub-index within the current message (or frame) that is being transmitted.
+         *
+         * - For GNSS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to the subframe
+         *   number of the navigation message, in the range of 1-5.
+         *
+         * - For Glonass L1 C/A, this refers to the String number, in the range from 1-15.
+         *
+         * - For Galileo F/NAV, this refers to the page type in the range 1-6.
+         *
+         * - For Galileo I/NAV, this refers to the word type in the range 0-10+. A value of 0 is
+         *   only allowed if the Satellite is transmiting a Spare Word.
+         *
+         * - For Galileo in particular, the type information embedded within the data bits may be
+         *   even more useful in interpretation, than the nominal page and word types provided in
+         *   this field.
+         *
+         * - For SBAS, the submessage id corresponds to the message type, in the range 1-63.
+         *
+         * - For Beidou CNAV1, the submessage id corresponds to the subframe number of the
+         *   navigation message, in the range of 1-3.
+         *
+         * - For Beidou CNAV2, the submessage id corresponds to the message type, in the range 1-63.
+         *
+         * - For IRNSS L5 C/A, the submessage id corresponds to the subframe number of the
+         *   navigation message, in the range of 1-4.
+         */
+        int submessageId;
+
+        /**
+         * The data of the reported GNSS message. The bytes (or words) are specified
+         * using big endian format (MSB first).
+         *
+         * - For GNSS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+         *   words. Each word (30 bits) must fit into the last 30 bits in a
+         *   4-byte word (skip B31 and B32), with MSB first, for a total of 40
+         *   bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+         *   The standard followed is 1995 SPS Signal specification.
+         *
+         * - For Glonass L1 C/A, each string contains 85 data bits, including the
+         *   checksum.  These bits must fit into 11 bytes, with MSB first (skip
+         *   B86-B88), covering a time period of 2 seconds.
+         *   The standard followed is Glonass Interface Control Document Edition 5.1.
+         *
+         * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+         *   excluded). Each word must fit into 30-bytes, with MSB first (skip
+         *   B239, B240), covering a time period of 10 seconds. The standard
+         *   followed is European GNSS(Galileo) Signal in Space Interface
+         *   Control Document Issue 1.2.
+         *
+         * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+         *   a total of 2x114 = 228 bits, (sync & tail excluded) that must fit
+         *   into 29 bytes, with MSB first (skip B229-B232). The standard followed
+         *   is same as above.
+         *
+         * - For SBAS, each block consists of 250 data bits, that should be fit into 32 bytes. MSB
+         *   first (skip B251-B256).
+         *
+         * - For Beidou CNAV1, subframe #1 consists of 14 data bits, that should be fit into 2
+         *   bytes. MSB first (skip B15-B16).  subframe #2 consists of 600 bits that should be fit
+         *   into 75 bytes. subframe #3 consists of 264 data bits that should be fit into 33 bytes.
+         *
+         * - For Beidou CNAV2, each subframe consists of 288 data bits, that should be fit into 36
+         *   bytes.
+         *
+         * The data reported here must be the raw data as demodulated by the GNSS receiver, not data
+         * received from an external source (i.e. not from a server download.)
+         */
+        byte[] data;
+    }
+
+    /**
+     * The callback to report an available fragment of a GNSS navigation messages
+     * from the HAL.
+     *
+     * @param message - The GNSS navigation submessage/subframe representation.
+     */
+    void gnssNavigationMessageCb(in GnssNavigationMessage message);
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssNavigationMessageInterface.aidl b/gnss/aidl/android/hardware/gnss/IGnssNavigationMessageInterface.aidl
new file mode 100644
index 0000000..e2f57c3
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssNavigationMessageInterface.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.IGnssNavigationMessageCallback;
+
+/**
+ * Extended interface for GNSS navigation message reporting support.
+ */
+@VintfStability
+interface IGnssNavigationMessageInterface {
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     *
+     * After a successful call to 'setCallback' the HAL must begin to provide updates as
+     * they become available.
+     *
+     * @param callback handle to IGnssNavigationMessageCallack interface.
+     */
+    void setCallback(in IGnssNavigationMessageCallback 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/visibility_control/IGnssVisibilityControl.aidl b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
new file mode 100644
index 0000000..93c3f2c
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss.visibility_control;
+
+import android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback;
+
+/**
+ * Represents the GNSS location reporting permissions and notification interface.
+ *
+ * This interface is used to tell the GNSS HAL implementation whether the framework user has
+ * granted permission to the GNSS HAL implementation to provide GNSS location information for
+ * non-framework (NFW), non-user initiated emergency use cases, and to notify the framework user
+ * of these GNSS location information deliveries.
+ *
+ * For user initiated emergency cases (and for the configured extended emergency session duration),
+ * the GNSS HAL implementation must serve the emergency location supporting network initiated
+ * location requests immediately irrespective of this permission settings.
+ *
+ * There is no separate need for the GNSS HAL implementation to monitor the global device location
+ * on/off setting. Permission to use GNSS for non-framework use cases is expressly controlled
+ * by the method enableNfwLocationAccess(). The framework monitors the location permission settings
+ * of the configured proxy applications(s), and device location settings, and calls the method
+ * enableNfwLocationAccess() whenever the user control proxy applications have, or do not have,
+ * location permission. The proxy applications are used to provide user visibility and control of
+ * location access by the non-framework on/off device entities they are representing.
+ *
+ * For device user visibility, the GNSS HAL implementation must call the method
+ * IGnssVisibilityControlCallback.nfwNotifyCb() whenever location request is rejected or
+ * location information is provided to non-framework entities (on or off device). This includes
+ * the network initiated location requests for user-initiated emergency use cases as well.
+ *
+ * The HAL implementations that support this interface must not report GNSS location, measurement,
+ * status, or other information that can be used to derive user location to any entity when not
+ * expressly authorized by this HAL. This includes all endpoints for location information
+ * off the device, including carriers, vendors, OEM and others directly or indirectly.
+ */
+@VintfStability
+interface IGnssVisibilityControl {
+    /**
+     * Enables/disables non-framework entity location access permission in the GNSS HAL.
+     *
+     * The framework will call this method to update GNSS HAL implementation every time the
+     * framework user, through the given proxy application(s) and/or device location settings,
+     * explicitly grants/revokes the location access permission for non-framework, non-user
+     * initiated emergency use cases.
+     *
+     * Whenever the user location information is delivered to non-framework entities, the HAL
+     * implementation must call the method IGnssVisibilityControlCallback.nfwNotifyCb() to notify
+     * the framework for user visibility.
+     *
+     * @param proxyApps Full list of package names of proxy Android applications representing
+     * the non-framework location access entities (on/off the device) for which the framework
+     * user has granted non-framework location access permission. The GNSS HAL implementation
+     * must provide location information only to non-framework entities represented by these
+     * proxy applications.
+     *
+     * 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);
+
+    /**
+     * Registers the callback for HAL implementation to use.
+     *
+     * @param callback Handle to IGnssVisibilityControlCallback interface.
+     */
+    void setCallback(in IGnssVisibilityControlCallback callback);
+}
diff --git a/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
new file mode 100644
index 0000000..051fbe6
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.visibility_control;
+
+/**
+ * GNSS location reporting permissions and notification callback interface.
+ */
+@VintfStability
+interface IGnssVisibilityControlCallback {
+    /**
+     * Protocol stack that is requesting the non-framework location information.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum NfwProtocolStack {
+        /** Cellular control plane requests */
+        CTRL_PLANE = 0,
+
+        /** All types of SUPL requests */
+        SUPL = 1,
+
+        /** All types of requests from IMS */
+        IMS = 10,
+
+        /** All types of requests from SIM */
+        SIM = 11,
+
+        /** Requests from other protocol stacks */
+        OTHER_PROTOCOL_STACK = 100
+    }
+
+    /**
+     * Entity that is requesting/receiving the location information.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum NfwRequestor {
+        /** Wireless service provider */
+        CARRIER = 0,
+
+        /** Device manufacturer */
+        OEM = 10,
+
+        /** Modem chipset vendor */
+        MODEM_CHIPSET_VENDOR = 11,
+
+        /** GNSS chipset vendor */
+        GNSS_CHIPSET_VENDOR = 12,
+
+        /** Other chipset vendor */
+        OTHER_CHIPSET_VENDOR = 13,
+
+        /** Automobile client */
+        AUTOMOBILE_CLIENT = 20,
+
+        /** Other sources */
+        OTHER_REQUESTOR = 100
+    }
+
+    /**
+     * GNSS response type for non-framework location requests.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum NfwResponseType {
+        /** Request rejected because framework has not given permission for this use case */
+        REJECTED = 0,
+
+        /** Request accepted but could not provide location because of a failure */
+        ACCEPTED_NO_LOCATION_PROVIDED = 1,
+
+        /** Request accepted and location provided */
+        ACCEPTED_LOCATION_PROVIDED = 2,
+    }
+
+    /**
+     * Represents a non-framework location information request/response notification.
+     */
+    @VintfStability
+    parcelable NfwNotification {
+        /**
+         * Package name of the Android proxy application representing the non-framework
+         * entity that requested location. Set to empty string if unknown.
+         *
+         * For user-initiated emergency use cases, this field must be set to empty string
+         * and the inEmergencyMode field must be set to true.
+         */
+        String proxyAppPackageName;
+
+        /** Protocol stack that initiated the non-framework location request. */
+        NfwProtocolStack protocolStack;
+
+        /**
+         * Name of the protocol stack if protocolStack field is set to OTHER_PROTOCOL_STACK.
+         * Otherwise, set to empty string.
+         *
+         * This field is opaque to the framework and used for logging purposes.
+         */
+        String otherProtocolStackName;
+
+        /** Source initiating/receiving the location information. */
+        NfwRequestor requestor;
+
+        /**
+         * Identity of the endpoint receiving the location information. For example, carrier
+         * name, OEM name, SUPL SLP/E-SLP FQDN, chipset vendor name, etc.
+         *
+         * This field is opaque to the framework and used for logging purposes.
+         */
+        String requestorId;
+
+        /** Indicates whether location information was provided for this request. */
+        NfwResponseType responseType;
+
+        /** Is the device in user initiated emergency session. */
+        boolean inEmergencyMode;
+
+        /** Is cached location provided */
+        boolean isCachedLocation;
+    }
+
+    /**
+     * Callback to report a non-framework delivered location.
+     *
+     * The GNSS HAL implementation must call this method to notify the framework whenever
+     * a non-framework location request is made to the GNSS HAL.
+     *
+     * Non-framework entities like low power sensor hubs that request location from GNSS and
+     * only pass location information through Android framework controls are exempt from this
+     * power-spending reporting. However, low power sensor hubs or other chipsets which may send
+     * the location information to anywhere other than Android framework (which provides user
+     * visibility and control), must report location information use through this API whenever
+     * location information (or events driven by that location such as "home" location detection)
+     * leaves the domain of that low power chipset.
+     *
+     * To avoid overly spamming the framework, high speed location reporting of the exact same
+     * type may be throttled to report location at a lower rate than the actual report rate, as
+     * long as the location is reported with a latency of no more than the larger of 5 seconds,
+     * or the next the Android processor awake time. For example, if an Automotive client is
+     * getting location information from the GNSS location system at 20Hz, this method may be
+     * called at 1Hz. As another example, if a low power processor is getting location from the
+     * GNSS chipset, and the Android processor is asleep, the notification to the Android HAL may
+     * be delayed until the next wake of the Android processor.
+     *
+     * @param notification Non-framework delivered location request/response description.
+     */
+    void nfwNotifyCb(in NfwNotification notification);
+
+    /**
+     * Tells if the device is currently in an emergency session.
+     *
+     * Emergency session is defined as the device being actively in a user initiated emergency
+     * call or in post emergency call extension time period.
+     *
+     * If the GNSS HAL implementation cannot determine if the device is in emergency session
+     * mode, it must call this method to confirm that the device is in emergency session before
+     * serving network initiated emergency SUPL and Control Plane location requests.
+     *
+     * @return success True if the framework determines that the device is in emergency session.
+     */
+    boolean isInEmergencySession();
+}
diff --git a/gnss/aidl/default/AGnss.cpp b/gnss/aidl/default/AGnss.cpp
new file mode 100644
index 0000000..e8d5ef7
--- /dev/null
+++ b/gnss/aidl/default/AGnss.cpp
@@ -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.
+ */
+
+#define LOG_TAG "AGnssAidl"
+
+#include "AGnss.h"
+#include <inttypes.h>
+#include <log/log.h>
+
+namespace aidl::android::hardware::gnss {
+
+std::shared_ptr<IAGnssCallback> AGnss::sCallback = nullptr;
+
+ndk::ScopedAStatus AGnss::setCallback(const std::shared_ptr<IAGnssCallback>& callback) {
+    ALOGD("AGnss::setCallback");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AGnss::setServer(AGnssType type, const std::string& hostname, int port) {
+    ALOGD("AGnss::setServer: type: %s, hostname: %s, port: %d", toString(type).c_str(),
+          hostname.c_str(), port);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AGnss::dataConnOpen(int64_t networkHandle, const std::string& apn,
+                                       ApnIpType apnIpType) {
+    ALOGD("AGnss::dataConnOpen: networkHandle:%" PRId64 ", apn: %s, apnIpType %s", networkHandle,
+          apn.c_str(), toString(apnIpType).c_str());
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/AGnss.h b/gnss/aidl/default/AGnss.h
new file mode 100644
index 0000000..cd973e1
--- /dev/null
+++ b/gnss/aidl/default/AGnss.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/gnss/BnAGnss.h>
+
+namespace aidl::android::hardware::gnss {
+
+using AGnssType = IAGnssCallback::AGnssType;
+
+struct AGnss : public BnAGnss {
+  public:
+    ndk::ScopedAStatus setCallback(const std::shared_ptr<IAGnssCallback>& callback) override;
+    ndk::ScopedAStatus dataConnClosed() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus dataConnFailed() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus setServer(AGnssType type, const std::string& hostname, int port) override;
+    ndk::ScopedAStatus dataConnOpen(int64_t networkHandle, const std::string& apn,
+                                    ApnIpType apnIpType) override;
+
+  private:
+    // Synchronization lock for sCallback
+    mutable std::mutex mMutex;
+    // Guarded by mMutex
+    static std::shared_ptr<IAGnssCallback> sCallback;
+};
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
index c028dd7..29c26d1 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -52,15 +52,22 @@
         "android.hardware.gnss.measurement_corrections@1.1",
         "android.hardware.gnss.measurement_corrections@1.0",
         "android.hardware.gnss.visibility_control@1.0",
-        "android.hardware.gnss-V1-ndk",
+        "android.hardware.gnss.visibility_control-V1-ndk",
+        "android.hardware.gnss-V2-ndk",
     ],
     srcs: [
+        "AGnss.cpp",
         "Gnss.cpp",
+        "GnssBatching.cpp",
+        "GnssDebug.cpp",
+        "GnssGeofence.cpp",
         "GnssHidlHal.cpp",
+        "GnssNavigationMessageInterface.cpp",
         "GnssPowerIndication.cpp",
         "GnssPsds.cpp",
         "GnssConfiguration.cpp",
         "GnssMeasurementInterface.cpp",
+        "GnssVisibilityControl.cpp",
         "service.cpp",
     ],
     static_libs: [
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index 6061eec..afb7b95 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -18,9 +18,15 @@
 
 #include "Gnss.h"
 #include <log/log.h>
+#include "AGnss.h"
+#include "GnssBatching.h"
 #include "GnssConfiguration.h"
+#include "GnssDebug.h"
+#include "GnssGeofence.h"
 #include "GnssMeasurementInterface.h"
+#include "GnssNavigationMessageInterface.h"
 #include "GnssPsds.h"
+#include "GnssVisibilityControl.h"
 
 namespace aidl::android::hardware::gnss {
 
@@ -53,6 +59,12 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Gnss::getExtensionAGnss(std::shared_ptr<IAGnss>* iAGnss) {
+    ALOGD("Gnss::getExtensionAGnss");
+    *iAGnss = SharedRefBase::make<AGnss>();
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus Gnss::getExtensionPsds(std::shared_ptr<IGnssPsds>* iGnssPsds) {
     ALOGD("Gnss::getExtensionPsds");
     *iGnssPsds = SharedRefBase::make<GnssPsds>();
@@ -88,4 +100,41 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Gnss::getExtensionGnssBatching(std::shared_ptr<IGnssBatching>* iGnssBatching) {
+    ALOGD("Gnss::getExtensionGnssBatching");
+
+    *iGnssBatching = SharedRefBase::make<GnssBatching>();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Gnss::getExtensionGnssGeofence(std::shared_ptr<IGnssGeofence>* iGnssGeofence) {
+    ALOGD("Gnss::getExtensionGnssGeofence");
+
+    *iGnssGeofence = SharedRefBase::make<GnssGeofence>();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Gnss::getExtensionGnssNavigationMessage(
+        std::shared_ptr<IGnssNavigationMessageInterface>* iGnssNavigationMessage) {
+    ALOGD("Gnss::getExtensionGnssNavigationMessage");
+
+    *iGnssNavigationMessage = SharedRefBase::make<GnssNavigationMessageInterface>();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Gnss::getExtensionGnssDebug(std::shared_ptr<IGnssDebug>* iGnssDebug) {
+    ALOGD("Gnss::getExtensionGnssDebug");
+
+    *iGnssDebug = SharedRefBase::make<GnssDebug>();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Gnss::getExtensionGnssVisibilityControl(
+        std::shared_ptr<visibility_control::IGnssVisibilityControl>* iGnssVisibilityControl) {
+    ALOGD("Gnss::getExtensionGnssVisibilityControl");
+
+    *iGnssVisibilityControl = SharedRefBase::make<visibility_control::GnssVisibilityControl>();
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h
index 76ebe4d..67fef94 100644
--- a/gnss/aidl/default/Gnss.h
+++ b/gnss/aidl/default/Gnss.h
@@ -16,11 +16,15 @@
 
 #pragma once
 
+#include <aidl/android/hardware/gnss/BnAGnss.h>
 #include <aidl/android/hardware/gnss/BnGnss.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/visibility_control/BnGnssVisibilityControl.h>
 #include "GnssConfiguration.h"
 #include "GnssPowerIndication.h"
 
@@ -37,6 +41,17 @@
             std::shared_ptr<IGnssPowerIndication>* iGnssPowerIndication) override;
     ndk::ScopedAStatus getExtensionGnssMeasurement(
             std::shared_ptr<IGnssMeasurementInterface>* iGnssMeasurement) override;
+    ndk::ScopedAStatus getExtensionGnssBatching(
+            std::shared_ptr<IGnssBatching>* iGnssBatching) override;
+    ndk::ScopedAStatus getExtensionGnssGeofence(
+            std::shared_ptr<IGnssGeofence>* iGnssGeofence) override;
+    ndk::ScopedAStatus getExtensionGnssNavigationMessage(
+            std::shared_ptr<IGnssNavigationMessageInterface>* iGnssNavigationMessage) override;
+    ndk::ScopedAStatus getExtensionAGnss(std::shared_ptr<IAGnss>* iAGnss) override;
+    ndk::ScopedAStatus getExtensionGnssDebug(std::shared_ptr<IGnssDebug>* iGnssDebug) override;
+    ndk::ScopedAStatus getExtensionGnssVisibilityControl(
+            std::shared_ptr<android::hardware::gnss::visibility_control::IGnssVisibilityControl>*
+                    iGnssVisibilityControl) override;
 
     std::shared_ptr<GnssConfiguration> mGnssConfiguration;
     std::shared_ptr<GnssPowerIndication> mGnssPowerIndication;
diff --git a/gnss/aidl/default/GnssBatching.cpp b/gnss/aidl/default/GnssBatching.cpp
new file mode 100644
index 0000000..b8be5e5
--- /dev/null
+++ b/gnss/aidl/default/GnssBatching.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssBatchingAidl"
+
+#include "GnssBatching.h"
+#include <aidl/android/hardware/gnss/BnGnss.h>
+#include <inttypes.h>
+#include <log/log.h>
+#include <utils/SystemClock.h>
+#include "Utils.h"
+
+namespace aidl::android::hardware::gnss {
+
+using namespace ::android::hardware::gnss;
+
+constexpr int BATCH_SIZE = 10;
+
+std::shared_ptr<IGnssBatchingCallback> GnssBatching::sCallback = nullptr;
+
+GnssBatching::GnssBatching()
+    : mMinIntervalMs(1000),
+      mWakeUpOnFifoFull(false),
+      mBatchedLocations(std::vector<GnssLocation>()) {}
+GnssBatching::~GnssBatching() {
+    cleanup();
+}
+
+ndk::ScopedAStatus GnssBatching::init(const std::shared_ptr<IGnssBatchingCallback>& callback) {
+    ALOGD("init");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssBatching::getBatchSize(int* size) {
+    ALOGD("getBatchingSize");
+    *size = BATCH_SIZE;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssBatching::start(int64_t periodNanos, int flags) {
+    ALOGD("start: periodNanos=%" PRId64 ", flags=%d", periodNanos, 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;
+    mMinIntervalMs = periodNanos / 1e6;
+
+    mIsActive = true;
+    mThread = std::thread([this]() {
+        while (mIsActive == true) {
+            const auto location = common::Utils::getMockLocation();
+            this->batchLocation(location);
+            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
+        }
+    });
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssBatching::flush() {
+    ALOGD("flush");
+    std::vector<GnssLocation> copy = std::vector<GnssLocation>(mBatchedLocations);
+    ndk::ScopedAStatus status;
+    if (sCallback != nullptr) {
+        sCallback->gnssLocationBatchCb(copy);
+        status = ndk::ScopedAStatus::ok();
+    } else {
+        ALOGE("GnssBatchingCallback is null. flush() failed.");
+        status = ndk::ScopedAStatus::fromServiceSpecificError(IGnss::ERROR_GENERIC);
+    }
+    mBatchedLocations.clear();
+    return status;
+}
+
+ndk::ScopedAStatus GnssBatching::stop() {
+    ALOGD("stop");
+    // Do not call flush() at stop()
+    mIsActive = false;
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssBatching::cleanup() {
+    ALOGD("cleanup");
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (mIsActive) {
+        stop();
+    }
+    flush();
+
+    sCallback = nullptr;
+    return ndk::ScopedAStatus::ok();
+}
+
+void GnssBatching::batchLocation(const GnssLocation& location) {
+    if (mBatchedLocations.size() > BATCH_SIZE) {
+        mBatchedLocations.erase(mBatchedLocations.begin());
+    }
+    mBatchedLocations.push_back(location);
+    if (mWakeUpOnFifoFull && mBatchedLocations.size() == BATCH_SIZE) {
+        flush();
+    }
+}
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssBatching.h b/gnss/aidl/default/GnssBatching.h
new file mode 100644
index 0000000..7cd6e85
--- /dev/null
+++ b/gnss/aidl/default/GnssBatching.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/gnss/BnGnssBatching.h>
+#include <atomic>
+#include <thread>
+
+namespace aidl::android::hardware::gnss {
+
+struct GnssBatching : public BnGnssBatching {
+  public:
+    GnssBatching();
+    ~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 flush() override;
+    ndk::ScopedAStatus stop() override;
+    ndk::ScopedAStatus cleanup() override;
+
+  private:
+    void batchLocation(const GnssLocation&);
+
+    // Guarded by mMutex
+    static std::shared_ptr<IGnssBatchingCallback> sCallback;
+
+    std::thread mThread;
+    std::atomic<bool> mIsActive;
+    std::atomic<long> mMinIntervalMs;
+    std::atomic<bool> mWakeUpOnFifoFull;
+
+    // Synchronization lock for sCallback
+    mutable std::mutex mMutex;
+
+    std::vector<GnssLocation> mBatchedLocations;
+};
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssDebug.cpp b/gnss/aidl/default/GnssDebug.cpp
new file mode 100644
index 0000000..f40c0bc
--- /dev/null
+++ b/gnss/aidl/default/GnssDebug.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssDebugAidl"
+
+#include "GnssDebug.h"
+#include <log/log.h>
+#include "MockLocation.h"
+
+namespace aidl::android::hardware::gnss {
+
+ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) {
+    ALOGD("GnssDebug::getDebugData");
+
+    PositionDebug positionDebug = {.valid = true,
+                                   .latitudeDegrees = 37.4219999,
+                                   .longitudeDegrees = -122.0840575,
+                                   .altitudeMeters = 1.60062531,
+                                   .speedMetersPerSec = 0,
+                                   .bearingDegrees = 0,
+                                   .horizontalAccuracyMeters = 5,
+                                   .verticalAccuracyMeters = 5,
+                                   .speedAccuracyMetersPerSecond = 1,
+                                   .bearingAccuracyDegrees = 90,
+                                   .ageSeconds = 0.99};
+    TimeDebug timeDebug = {.timeEstimateMs = 1519930775453L,
+                           .timeUncertaintyNs = 1000,
+                           .frequencyUncertaintyNsPerSec = 5.0e4};
+    std::vector<SatelliteData> satelliteDataArrayDebug = {};
+    debugData->position = positionDebug;
+    debugData->time = timeDebug;
+    debugData->satelliteDataArray = satelliteDataArrayDebug;
+
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssDebug.h b/gnss/aidl/default/GnssDebug.h
new file mode 100644
index 0000000..001d47c
--- /dev/null
+++ b/gnss/aidl/default/GnssDebug.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/gnss/BnGnssDebug.h>
+
+namespace aidl::android::hardware::gnss {
+
+struct GnssDebug : public BnGnssDebug {
+  public:
+    ndk::ScopedAStatus getDebugData(DebugData* debugData) override;
+};
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssGeofence.cpp b/gnss/aidl/default/GnssGeofence.cpp
new file mode 100644
index 0000000..eda33cc
--- /dev/null
+++ b/gnss/aidl/default/GnssGeofence.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssGeofenceAidl"
+
+#include "GnssGeofence.h"
+#include <aidl/android/hardware/gnss/BnGnssGeofence.h>
+#include <log/log.h>
+
+namespace aidl::android::hardware::gnss {
+
+std::shared_ptr<IGnssGeofenceCallback> GnssGeofence::sCallback = nullptr;
+
+ndk::ScopedAStatus GnssGeofence::setCallback(
+        const std::shared_ptr<IGnssGeofenceCallback>& callback) {
+    ALOGD("setCallback");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssGeofence::addGeofence(int geofenceId, double latitudeDegrees,
+                                             double longitudeDegrees, double radiusMeters,
+                                             int lastTransition, int monitorTransitions,
+                                             int notificationResponsivenessMs, int unknownTimerMs) {
+    ALOGD("addGeofence. geofenceId=%d, lat=%lf, lng=%lf, rad=%lf, lastTransition=%d, "
+          "monitorTransitions=%d, notificationResponsivenessMs=%d, unknownTimerMs=%d",
+          geofenceId, latitudeDegrees, longitudeDegrees, radiusMeters, lastTransition,
+          monitorTransitions, notificationResponsivenessMs, unknownTimerMs);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssGeofence::pauseGeofence(int geofenceId) {
+    ALOGD("pauseGeofence. id=%d", geofenceId);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssGeofence::resumeGeofence(int geofenceId, int monitorTransitions) {
+    ALOGD("resumeGeofence. id=%d, monitorTransitions=%d", geofenceId, monitorTransitions);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssGeofence::removeGeofence(int geofenceId) {
+    ALOGD("removeGeofence. id=%d", geofenceId);
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssGeofence.h b/gnss/aidl/default/GnssGeofence.h
new file mode 100644
index 0000000..313e832
--- /dev/null
+++ b/gnss/aidl/default/GnssGeofence.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/gnss/BnGnssGeofence.h>
+
+namespace aidl::android::hardware::gnss {
+
+struct GnssGeofence : public BnGnssGeofence {
+  public:
+    ndk::ScopedAStatus setCallback(const std::shared_ptr<IGnssGeofenceCallback>& callback) override;
+    ndk::ScopedAStatus addGeofence(int geofenceId, double latitudeDegrees, double longitudeDegrees,
+                                   double radiusMeters, int lastTransition, int monitorTransitions,
+                                   int notificationResponsivenessMs, int unknownTimerMs) override;
+    ndk::ScopedAStatus pauseGeofence(int geofenceId) override;
+    ndk::ScopedAStatus resumeGeofence(int geofenceId, int monitorTransitions) override;
+    ndk::ScopedAStatus removeGeofence(int geofenceId) override;
+
+  private:
+    // Guarded by mMutex
+    static std::shared_ptr<IGnssGeofenceCallback> sCallback;
+
+    // Synchronization lock for sCallback
+    mutable std::mutex mMutex;
+};
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp
index fcc1f98..9e4f7c7 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.cpp
+++ b/gnss/aidl/default/GnssMeasurementInterface.cpp
@@ -19,11 +19,17 @@
 #include "GnssMeasurementInterface.h"
 #include <aidl/android/hardware/gnss/BnGnss.h>
 #include <log/log.h>
+#include "DeviceFileReader.h"
+#include "GnssRawMeasurementParser.h"
+#include "GnssReplayUtils.h"
 #include "Utils.h"
 
 namespace aidl::android::hardware::gnss {
 
 using Utils = ::android::hardware::gnss::common::Utils;
+using ReplayUtils = ::android::hardware::gnss::common::ReplayUtils;
+using GnssRawMeasurementParser = ::android::hardware::gnss::common::GnssRawMeasurementParser;
+using DeviceFileReader = ::android::hardware::gnss::common::DeviceFileReader;
 
 std::shared_ptr<IGnssMeasurementCallback> GnssMeasurementInterface::sCallback = nullptr;
 
@@ -63,9 +69,22 @@
     mIsActive = true;
     mThread = std::thread([this, enableCorrVecOutputs]() {
         while (mIsActive == true) {
-            auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
-            this->reportMeasurement(measurement);
-
+            std::string rawMeasurementStr = "";
+            if (ReplayUtils::hasGnssDeviceFile() &&
+                ReplayUtils::isGnssRawMeasurement(
+                        rawMeasurementStr =
+                                DeviceFileReader::Instance().getGnssRawMeasurementData())) {
+                ALOGD("rawMeasurementStr(size: %zu) from device file: %s", rawMeasurementStr.size(),
+                      rawMeasurementStr.c_str());
+                auto measurement =
+                        GnssRawMeasurementParser::getMeasurementFromStrs(rawMeasurementStr);
+                if (measurement != nullptr) {
+                    this->reportMeasurement(*measurement);
+                }
+            } else {
+                auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
+                this->reportMeasurement(measurement);
+            }
             std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
         }
     });
diff --git a/gnss/aidl/default/GnssNavigationMessageInterface.cpp b/gnss/aidl/default/GnssNavigationMessageInterface.cpp
new file mode 100644
index 0000000..4bc859d
--- /dev/null
+++ b/gnss/aidl/default/GnssNavigationMessageInterface.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssNavigationMessageAidl"
+
+#include "GnssNavigationMessageInterface.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 GnssNavigationMessage = IGnssNavigationMessageCallback::GnssNavigationMessage;
+using GnssNavigationMessageType = GnssNavigationMessage::GnssNavigationMessageType;
+
+std::shared_ptr<IGnssNavigationMessageCallback> GnssNavigationMessageInterface::sCallback = nullptr;
+
+GnssNavigationMessageInterface::GnssNavigationMessageInterface() : mMinIntervalMillis(1000) {}
+
+GnssNavigationMessageInterface::~GnssNavigationMessageInterface() {
+    stop();
+}
+
+ndk::ScopedAStatus GnssNavigationMessageInterface::setCallback(
+        const std::shared_ptr<IGnssNavigationMessageCallback>& callback) {
+    ALOGD("setCallback");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+    start();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssNavigationMessageInterface::close() {
+    ALOGD("close");
+    stop();
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = nullptr;
+    return ndk::ScopedAStatus::ok();
+}
+
+void GnssNavigationMessageInterface::start() {
+    ALOGD("start");
+    mIsActive = true;
+    mThread = std::thread([this]() {
+        while (mIsActive == true) {
+            GnssNavigationMessage message = {
+                    .svid = 19,
+                    .type = GnssNavigationMessageType::GPS_L1CA,
+                    .status = GnssNavigationMessage::STATUS_PARITY_PASSED,
+                    .messageId = 2,
+                    .submessageId = 3,
+                    .data = std::vector<uint8_t>(40, 0xF9),
+            };
+            this->reportMessage(message);
+            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
+        }
+    });
+    mThread.detach();
+}
+
+void GnssNavigationMessageInterface::stop() {
+    ALOGD("stop");
+    mIsActive = false;
+}
+
+void GnssNavigationMessageInterface::reportMessage(const GnssNavigationMessage& message) {
+    ALOGD("reportMessage()");
+    std::shared_ptr<IGnssNavigationMessageCallback> callbackCopy;
+    {
+        std::unique_lock<std::mutex> lock(mMutex);
+        if (sCallback == nullptr) {
+            ALOGE("%s: GnssNavigationMessageInterface::sCallback is null.", __func__);
+            return;
+        }
+        callbackCopy = sCallback;
+    }
+    callbackCopy->gnssNavigationMessageCb(message);
+}
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssNavigationMessageInterface.h b/gnss/aidl/default/GnssNavigationMessageInterface.h
new file mode 100644
index 0000000..600b23a
--- /dev/null
+++ b/gnss/aidl/default/GnssNavigationMessageInterface.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/gnss/BnGnssNavigationMessageInterface.h>
+#include <atomic>
+#include <thread>
+
+namespace aidl::android::hardware::gnss {
+
+struct GnssNavigationMessageInterface : public BnGnssNavigationMessageInterface {
+  public:
+    GnssNavigationMessageInterface();
+    ~GnssNavigationMessageInterface();
+    ndk::ScopedAStatus setCallback(
+            const std::shared_ptr<IGnssNavigationMessageCallback>& callback) override;
+    ndk::ScopedAStatus close() override;
+
+  private:
+    void start();
+    void stop();
+    void reportMessage(const IGnssNavigationMessageCallback::GnssNavigationMessage& message);
+
+    std::atomic<long> mMinIntervalMillis;
+    std::atomic<bool> mIsActive;
+    std::thread mThread;
+
+    // Guarded by mMutex
+    static std::shared_ptr<IGnssNavigationMessageCallback> sCallback;
+    // Synchronization lock for sCallback
+    mutable std::mutex mMutex;
+};
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssVisibilityControl.cpp b/gnss/aidl/default/GnssVisibilityControl.cpp
new file mode 100644
index 0000000..208d73c
--- /dev/null
+++ b/gnss/aidl/default/GnssVisibilityControl.cpp
@@ -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.
+ */
+
+#define LOG_TAG "GnssVisibilityControl"
+
+#include "GnssVisibilityControl.h"
+#include <log/log.h>
+
+namespace aidl::android::hardware::gnss::visibility_control {
+
+std::shared_ptr<IGnssVisibilityControlCallback> GnssVisibilityControl::sCallback = nullptr;
+
+ndk::ScopedAStatus GnssVisibilityControl::enableNfwLocationAccess(
+        const std::vector<std::string>& proxyApps) {
+    std::string os;
+    bool first = true;
+    for (const auto& proxyApp : proxyApps) {
+        if (first) {
+            first = false;
+        } else {
+            os += " ";
+        }
+        os += proxyApp;
+    }
+
+    ALOGD("GnssVisibilityControl::enableNfwLocationAccess proxyApps: %s", os.c_str());
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssVisibilityControl::setCallback(
+        const std::shared_ptr<IGnssVisibilityControlCallback>& callback) {
+    ALOGD("GnssVisibilityControl::setCallback");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::gnss::visibility_control
diff --git a/gnss/aidl/default/GnssVisibilityControl.h b/gnss/aidl/default/GnssVisibilityControl.h
new file mode 100644
index 0000000..5b36442
--- /dev/null
+++ b/gnss/aidl/default/GnssVisibilityControl.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/visibility_control/BnGnssVisibilityControl.h>
+
+namespace aidl::android::hardware::gnss::visibility_control {
+
+struct GnssVisibilityControl : public BnGnssVisibilityControl {
+  public:
+    ndk::ScopedAStatus enableNfwLocationAccess(const std::vector<std::string>& hostname) override;
+    ndk::ScopedAStatus setCallback(
+            const std::shared_ptr<IGnssVisibilityControlCallback>& callback) override;
+
+  private:
+    // Synchronization lock for sCallback
+    mutable std::mutex mMutex;
+    // Guarded by mMutex
+    static std::shared_ptr<IGnssVisibilityControlCallback> sCallback;
+};
+
+}  // namespace aidl::android::hardware::gnss::visibility_control
diff --git a/gnss/aidl/default/gnss-default.xml b/gnss/aidl/default/gnss-default.xml
index 2b06cd2..7449310 100644
--- a/gnss/aidl/default/gnss-default.xml
+++ b/gnss/aidl/default/gnss-default.xml
@@ -1,6 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.gnss</name>
+        <version>2</version>
         <interface>
             <name>IGnss</name>
             <instance>default</instance>
diff --git a/gnss/aidl/vts/AGnssCallbackAidl.cpp b/gnss/aidl/vts/AGnssCallbackAidl.cpp
new file mode 100644
index 0000000..3327835
--- /dev/null
+++ b/gnss/aidl/vts/AGnssCallbackAidl.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AGnssCallbackAidl.h"
+#include <log/log.h>
+
+android::binder::Status AGnssCallbackAidl::agnssStatusCb(const AGnssType type,
+                                                         const AGnssStatusValue status) {
+    ALOGI("agnssStatusCb type %d status %d", type, status);
+    return android::binder::Status::ok();
+}
diff --git a/gnss/aidl/vts/AGnssCallbackAidl.h b/gnss/aidl/vts/AGnssCallbackAidl.h
new file mode 100644
index 0000000..6173e85
--- /dev/null
+++ b/gnss/aidl/vts/AGnssCallbackAidl.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/BnAGnssCallback.h>
+
+using AGnssType = android::hardware::gnss::IAGnssCallback::AGnssType;
+using AGnssStatusValue = android::hardware::gnss::IAGnssCallback::AGnssStatusValue;
+
+/** Implementation for IAGnssCallback. */
+class AGnssCallbackAidl : public android::hardware::gnss::BnAGnssCallback {
+  public:
+    AGnssCallbackAidl(){};
+    ~AGnssCallbackAidl(){};
+    android::binder::Status agnssStatusCb(const AGnssType type,
+                                          const AGnssStatusValue status) override;
+};
diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp
index 838849d..d532fad 100644
--- a/gnss/aidl/vts/Android.bp
+++ b/gnss/aidl/vts/Android.bp
@@ -30,9 +30,14 @@
     srcs: [
         "gnss_hal_test.cpp",
         "gnss_hal_test_cases.cpp",
+        "AGnssCallbackAidl.cpp",
+        "GnssBatchingCallback.cpp",
         "GnssCallbackAidl.cpp",
+        "GnssGeofenceCallback.cpp",
         "GnssMeasurementCallbackAidl.cpp",
+        "GnssNavigationMessageCallback.cpp",
         "GnssPowerIndicationCallback.cpp",
+        "GnssVisibilityControlCallback.cpp",
         "VtsHalGnssTargetTest.cpp",
     ],
     shared_libs: [
@@ -43,8 +48,9 @@
         "libbinder",
     ],
     static_libs: [
-        "android.hardware.gnss-V1-cpp",
+        "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/GnssBatchingCallback.cpp b/gnss/aidl/vts/GnssBatchingCallback.cpp
new file mode 100644
index 0000000..2da3b12
--- /dev/null
+++ b/gnss/aidl/vts/GnssBatchingCallback.cpp
@@ -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.
+ */
+
+#include "GnssBatchingCallback.h"
+#include <inttypes.h>
+#include <log/log.h>
+
+android::binder::Status GnssBatchingCallback::gnssLocationBatchCb(
+        const std::vector<android::hardware::gnss::GnssLocation>& locations) {
+    ALOGI("Batched locations received with size=%d", (int)locations.size());
+    for (const auto& location : locations) {
+        ALOGI("elapsedRealtime: flags = %d, timestampNs: %" PRId64 ", timeUncertaintyNs=%lf",
+              location.elapsedRealtime.flags, location.elapsedRealtime.timestampNs,
+              location.elapsedRealtime.timeUncertaintyNs);
+    }
+    batched_locations_cbq_.store(locations);
+    return android::binder::Status::ok();
+}
diff --git a/gnss/aidl/vts/GnssBatchingCallback.h b/gnss/aidl/vts/GnssBatchingCallback.h
new file mode 100644
index 0000000..310a134
--- /dev/null
+++ b/gnss/aidl/vts/GnssBatchingCallback.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/BnGnssBatchingCallback.h>
+#include <vector>
+#include "GnssCallbackEventQueue.h"
+
+/** Implementation for IGnssBatchingCallback. */
+class GnssBatchingCallback : public android::hardware::gnss::BnGnssBatchingCallback {
+  public:
+    GnssBatchingCallback() : batched_locations_cbq_("batched_locations") {}
+    ~GnssBatchingCallback() {}
+
+    android::binder::Status gnssLocationBatchCb(
+            const std::vector<android::hardware::gnss::GnssLocation>& locations) override;
+
+    android::hardware::gnss::common::GnssCallbackEventQueue<
+            std::vector<android::hardware::gnss::GnssLocation>>
+            batched_locations_cbq_;
+    std::vector<android::hardware::gnss::GnssLocation> last_batched_locations_;
+};
diff --git a/gnss/aidl/vts/GnssGeofenceCallback.cpp b/gnss/aidl/vts/GnssGeofenceCallback.cpp
new file mode 100644
index 0000000..b841cb9
--- /dev/null
+++ b/gnss/aidl/vts/GnssGeofenceCallback.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GnssGeofenceCallback.h"
+#include <log/log.h>
+
+using android::binder::Status;
+using android::hardware::gnss::GnssLocation;
+
+Status GnssGeofenceCallback::gnssGeofenceTransitionCb(int, const GnssLocation&, int, int64_t) {
+    // To implement
+    return Status::ok();
+}
+Status GnssGeofenceCallback::gnssGeofenceStatusCb(int, const GnssLocation&) {
+    // To implement
+    return Status::ok();
+}
+Status GnssGeofenceCallback::gnssGeofenceAddCb(int, int) {
+    // To implement
+    return Status::ok();
+}
+Status GnssGeofenceCallback::gnssGeofenceRemoveCb(int, int) {
+    // To implement
+    return Status::ok();
+}
+Status GnssGeofenceCallback::gnssGeofencePauseCb(int, int) {
+    // To implement
+    return Status::ok();
+}
+Status GnssGeofenceCallback::gnssGeofenceResumeCb(int, int) {
+    // To implement
+    return Status::ok();
+}
diff --git a/gnss/aidl/vts/GnssGeofenceCallback.h b/gnss/aidl/vts/GnssGeofenceCallback.h
new file mode 100644
index 0000000..b105518
--- /dev/null
+++ b/gnss/aidl/vts/GnssGeofenceCallback.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/BnGnssGeofenceCallback.h>
+#include <vector>
+#include "GnssCallbackEventQueue.h"
+
+/** Implementation for IGnssGeofenceCallback. */
+class GnssGeofenceCallback : public android::hardware::gnss::BnGnssGeofenceCallback {
+  public:
+    GnssGeofenceCallback() {}
+    ~GnssGeofenceCallback() {}
+
+    android::binder::Status gnssGeofenceTransitionCb(
+            int geofenceId, const android::hardware::gnss::GnssLocation& location, int transition,
+            int64_t timestampMillis) override;
+    android::binder::Status gnssGeofenceStatusCb(
+            int availability, const android::hardware::gnss::GnssLocation& lastLocation) override;
+    android::binder::Status gnssGeofenceAddCb(int geofenceId, int status) override;
+    android::binder::Status gnssGeofenceRemoveCb(int geofenceId, int status) override;
+    android::binder::Status gnssGeofencePauseCb(int geofenceId, int status) override;
+    android::binder::Status gnssGeofenceResumeCb(int geofenceId, int status) override;
+};
diff --git a/gnss/aidl/vts/GnssNavigationMessageCallback.cpp b/gnss/aidl/vts/GnssNavigationMessageCallback.cpp
new file mode 100644
index 0000000..cf4a6eb
--- /dev/null
+++ b/gnss/aidl/vts/GnssNavigationMessageCallback.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "GnssNavMsgCallback"
+
+#include "GnssNavigationMessageCallback.h"
+#include <log/log.h>
+
+android::binder::Status GnssNavigationMessageCallback::gnssNavigationMessageCb(
+        const android::hardware::gnss::IGnssNavigationMessageCallback::GnssNavigationMessage& msg) {
+    ALOGD("gnssNavigationMessageCb. svid=%d, type=%d, status=%d, msgId=%d, subMsgId=%d, "
+          "data.size=%d",
+          msg.svid, (int)msg.type, (int)msg.status, msg.messageId, msg.submessageId,
+          (int)msg.data.size());
+    return android::binder::Status::ok();
+}
diff --git a/gnss/aidl/vts/GnssNavigationMessageCallback.h b/gnss/aidl/vts/GnssNavigationMessageCallback.h
new file mode 100644
index 0000000..55114ca
--- /dev/null
+++ b/gnss/aidl/vts/GnssNavigationMessageCallback.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/BnGnssNavigationMessageCallback.h>
+
+/** Implementation for IGnssNavigationMessageCallback. */
+class GnssNavigationMessageCallback
+    : public android::hardware::gnss::BnGnssNavigationMessageCallback {
+  public:
+    GnssNavigationMessageCallback() {}
+    ~GnssNavigationMessageCallback() {}
+
+    android::binder::Status gnssNavigationMessageCb(
+            const android::hardware::gnss::IGnssNavigationMessageCallback::GnssNavigationMessage&
+                    message) override;
+};
diff --git a/gnss/aidl/vts/GnssVisibilityControlCallback.cpp b/gnss/aidl/vts/GnssVisibilityControlCallback.cpp
new file mode 100644
index 0000000..aa27af1
--- /dev/null
+++ b/gnss/aidl/vts/GnssVisibilityControlCallback.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GnssVisibilityControlCallback.h"
+#include <log/log.h>
+
+android::binder::Status GnssVisibilityControlCallback::nfwNotifyCb(const NfwNotification&) {
+    // To implement
+    return android::binder::Status::ok();
+}
+
+android::binder::Status GnssVisibilityControlCallback::isInEmergencySession(bool*) {
+    // To implement
+    return android::binder::Status::ok();
+}
diff --git a/gnss/aidl/vts/GnssVisibilityControlCallback.h b/gnss/aidl/vts/GnssVisibilityControlCallback.h
new file mode 100644
index 0000000..fbacde7
--- /dev/null
+++ b/gnss/aidl/vts/GnssVisibilityControlCallback.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/visibility_control/BnGnssVisibilityControlCallback.h>
+
+class GnssVisibilityControlCallback
+    : public android::hardware::gnss::visibility_control::BnGnssVisibilityControlCallback {
+  public:
+    GnssVisibilityControlCallback(){};
+    ~GnssVisibilityControlCallback(){};
+    android::binder::Status nfwNotifyCb(
+            const android::hardware::gnss::visibility_control::IGnssVisibilityControlCallback::
+                    NfwNotification& notification) override;
+    android::binder::Status isInEmergencySession(bool* _aidl_return) override;
+};
diff --git a/gnss/aidl/vts/gnss_hal_test.h b/gnss/aidl/vts/gnss_hal_test.h
index f72f7fe..e3ecbed 100644
--- a/gnss/aidl/vts/gnss_hal_test.h
+++ b/gnss/aidl/vts/gnss_hal_test.h
@@ -23,6 +23,7 @@
 #include <binder/IServiceManager.h>
 
 #include <android/hardware/gnss/2.1/IGnss.h>
+#include "GnssBatchingCallback.h"
 #include "GnssCallbackAidl.h"
 #include "v2_1/gnss_hal_test_template.h"
 
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 0cd782e..90b643c 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -16,13 +16,23 @@
 
 #define LOG_TAG "GnssHalTestCases"
 
+#include <android/hardware/gnss/IAGnss.h>
 #include <android/hardware/gnss/IGnss.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/visibility_control/IGnssVisibilityControl.h>
+#include <cutils/properties.h>
+#include "AGnssCallbackAidl.h"
+#include "GnssBatchingCallback.h"
+#include "GnssGeofenceCallback.h"
 #include "GnssMeasurementCallbackAidl.h"
+#include "GnssNavigationMessageCallback.h"
 #include "GnssPowerIndicationCallback.h"
+#include "GnssVisibilityControlCallback.h"
 #include "gnss_hal_test.h"
 
 using android::sp;
@@ -32,17 +42,31 @@
 using android::hardware::gnss::GnssData;
 using android::hardware::gnss::GnssMeasurement;
 using android::hardware::gnss::GnssPowerStats;
+using android::hardware::gnss::IAGnss;
 using android::hardware::gnss::IGnss;
+using android::hardware::gnss::IGnssBatching;
+using android::hardware::gnss::IGnssBatchingCallback;
 using android::hardware::gnss::IGnssConfiguration;
+using android::hardware::gnss::IGnssDebug;
+using android::hardware::gnss::IGnssGeofence;
+using android::hardware::gnss::IGnssGeofenceCallback;
 using android::hardware::gnss::IGnssMeasurementCallback;
 using android::hardware::gnss::IGnssMeasurementInterface;
+using android::hardware::gnss::IGnssNavigationMessageInterface;
 using android::hardware::gnss::IGnssPowerIndication;
 using android::hardware::gnss::IGnssPsds;
 using android::hardware::gnss::PsdsType;
 using android::hardware::gnss::SatellitePvt;
+using android::hardware::gnss::visibility_control::IGnssVisibilityControl;
 
 using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType;
 
+static bool IsAutomotiveDevice() {
+    char buffer[PROPERTY_VALUE_MAX] = {0};
+    property_get("ro.hardware.type", buffer, "");
+    return strncmp(buffer, "automotive", PROPERTY_VALUE_MAX) == 0;
+}
+
 /*
  * SetupTeardownCreateCleanup:
  * Requests the gnss HAL then calls cleanup
@@ -749,3 +773,133 @@
     status = gnss_configuration_hal->setBlocklist(sources);
     ASSERT_TRUE(status.isOk());
 }
+
+/*
+ * TestAllExtensions.
+ */
+TEST_P(GnssHalTest, TestAllExtensions) {
+    sp<IGnssBatching> iGnssBatching;
+    auto status = aidl_gnss_hal_->getExtensionGnssBatching(&iGnssBatching);
+    if (status.isOk() && iGnssBatching != nullptr) {
+        auto gnssBatchingCallback = sp<GnssBatchingCallback>::make();
+        status = iGnssBatching->init(gnssBatchingCallback);
+        ASSERT_TRUE(status.isOk());
+
+        status = iGnssBatching->cleanup();
+        ASSERT_TRUE(status.isOk());
+    }
+
+    sp<IGnssGeofence> iGnssGeofence;
+    status = aidl_gnss_hal_->getExtensionGnssGeofence(&iGnssGeofence);
+    if (status.isOk() && iGnssGeofence != nullptr) {
+        auto gnssGeofenceCallback = sp<GnssGeofenceCallback>::make();
+        status = iGnssGeofence->setCallback(gnssGeofenceCallback);
+        ASSERT_TRUE(status.isOk());
+    }
+
+    sp<IGnssNavigationMessageInterface> iGnssNavMsgIface;
+    status = aidl_gnss_hal_->getExtensionGnssNavigationMessage(&iGnssNavMsgIface);
+    if (status.isOk() && iGnssNavMsgIface != nullptr) {
+        auto gnssNavMsgCallback = sp<GnssNavigationMessageCallback>::make();
+        status = iGnssNavMsgIface->setCallback(gnssNavMsgCallback);
+        ASSERT_TRUE(status.isOk());
+
+        status = iGnssNavMsgIface->close();
+        ASSERT_TRUE(status.isOk());
+    }
+}
+
+/*
+ * TestAGnssExtension:
+ * 1. Gets the IAGnss extension.
+ * 2. Sets AGnssCallback.
+ * 3. Sets SUPL server host/port.
+ */
+TEST_P(GnssHalTest, TestAGnssExtension) {
+    if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+        return;
+    }
+    sp<IAGnss> iAGnss;
+    auto status = aidl_gnss_hal_->getExtensionAGnss(&iAGnss);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(iAGnss != nullptr);
+
+    auto agnssCallback = sp<AGnssCallbackAidl>::make();
+    status = iAGnss->setCallback(agnssCallback);
+    ASSERT_TRUE(status.isOk());
+
+    // Set SUPL server host/port
+    status = iAGnss->setServer(AGnssType::SUPL, String16("supl.google.com"), 7275);
+    ASSERT_TRUE(status.isOk());
+}
+
+/*
+ * GnssDebugValuesSanityTest:
+ * Ensures that GnssDebug values make sense.
+ */
+TEST_P(GnssHalTest, GnssDebugValuesSanityTest) {
+    if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+        return;
+    }
+    sp<IGnssDebug> iGnssDebug;
+    auto status = aidl_gnss_hal_->getExtensionGnssDebug(&iGnssDebug);
+    ASSERT_TRUE(status.isOk());
+
+    if (!IsAutomotiveDevice() && gnss_cb_->info_cbq_.calledCount() > 0) {
+        ASSERT_TRUE(iGnssDebug != nullptr);
+
+        IGnssDebug::DebugData data;
+        auto status = iGnssDebug->getDebugData(&data);
+        ASSERT_TRUE(status.isOk());
+
+        if (data.position.valid) {
+            ASSERT_TRUE(data.position.latitudeDegrees >= -90 &&
+                        data.position.latitudeDegrees <= 90);
+            ASSERT_TRUE(data.position.longitudeDegrees >= -180 &&
+                        data.position.longitudeDegrees <= 180);
+            ASSERT_TRUE(data.position.altitudeMeters >= -1000 &&  // Dead Sea: -414m
+                        data.position.altitudeMeters <= 20000);   // Mount Everest: 8850m
+            ASSERT_TRUE(data.position.speedMetersPerSec >= 0 &&
+                        data.position.speedMetersPerSec <= 600);
+            ASSERT_TRUE(data.position.bearingDegrees >= -360 &&
+                        data.position.bearingDegrees <= 360);
+            ASSERT_TRUE(data.position.horizontalAccuracyMeters > 0 &&
+                        data.position.horizontalAccuracyMeters <= 20000000);
+            ASSERT_TRUE(data.position.verticalAccuracyMeters > 0 &&
+                        data.position.verticalAccuracyMeters <= 20000);
+            ASSERT_TRUE(data.position.speedAccuracyMetersPerSecond > 0 &&
+                        data.position.speedAccuracyMetersPerSecond <= 500);
+            ASSERT_TRUE(data.position.bearingAccuracyDegrees > 0 &&
+                        data.position.bearingAccuracyDegrees <= 180);
+            ASSERT_TRUE(data.position.ageSeconds >= 0);
+        }
+        ASSERT_TRUE(data.time.timeEstimateMs >= 1483228800000);  // Jan 01 2017 00:00:00 GMT.
+        ASSERT_TRUE(data.time.timeUncertaintyNs > 0);
+        ASSERT_TRUE(data.time.frequencyUncertaintyNsPerSec > 0 &&
+                    data.time.frequencyUncertaintyNsPerSec <= 2.0e5);  // 200 ppm
+    }
+}
+
+/*
+ * TestAGnssExtension:
+ * TestGnssVisibilityControlExtension:
+ * 1. Gets the IGnssVisibilityControl extension.
+ * 2. Sets GnssVisibilityControlCallback
+ * 3. Sets proxy apps
+ */
+TEST_P(GnssHalTest, TestGnssVisibilityControlExtension) {
+    if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+        return;
+    }
+    sp<IGnssVisibilityControl> iGnssVisibilityControl;
+    auto status = aidl_gnss_hal_->getExtensionGnssVisibilityControl(&iGnssVisibilityControl);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(iGnssVisibilityControl != nullptr);
+    auto gnssVisibilityControlCallback = sp<GnssVisibilityControlCallback>::make();
+    status = iGnssVisibilityControl->setCallback(gnssVisibilityControlCallback);
+    ASSERT_TRUE(status.isOk());
+
+    std::vector<String16> proxyApps{String16("com.example.ims"), String16("com.example.mdt")};
+    status = iGnssVisibilityControl->enableNfwLocationAccess(proxyApps);
+    ASSERT_TRUE(status.isOk());
+}
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index a1d3123..05bec88 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -38,9 +38,13 @@
         "v2_1/GnssDebug.cpp",
         "v2_1/GnssMeasurement.cpp",
         "v2_1/GnssMeasurementCorrections.cpp",
+        "DeviceFileReader.cpp",
+        "GnssRawMeasurementParser.cpp",
+        "GnssReplayUtils.cpp",
         "MockLocation.cpp",
-        "Utils.cpp",
         "NmeaFixInfo.cpp",
+        "ParseUtils.cpp",
+        "Utils.cpp",
     ],
     export_include_dirs: ["include"],
     shared_libs: [
@@ -52,6 +56,6 @@
         "android.hardware.gnss@2.1",
         "android.hardware.gnss.measurement_corrections@1.1",
         "android.hardware.gnss.measurement_corrections@1.0",
-        "android.hardware.gnss-V1-ndk",
+        "android.hardware.gnss-V2-ndk",
     ],
 }
diff --git a/gnss/common/utils/default/DeviceFileReader.cpp b/gnss/common/utils/default/DeviceFileReader.cpp
new file mode 100644
index 0000000..7d4fb04
--- /dev/null
+++ b/gnss/common/utils/default/DeviceFileReader.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "DeviceFileReader.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+void DeviceFileReader::getDataFromDeviceFile(const std::string& command, int mMinIntervalMs) {
+    char inputBuffer[INPUT_BUFFER_SIZE];
+    int mGnssFd = open(ReplayUtils::getGnssPath().c_str(),
+                       O_RDWR | O_NONBLOCK);
+
+    if (mGnssFd == -1) {
+        return;
+    }
+
+    int bytes_write = write(mGnssFd, command.c_str(), command.size());
+    if (bytes_write <= 0) {
+        close(mGnssFd);
+        return;
+    }
+
+    struct epoll_event ev, events[1];
+    ev.data.fd = mGnssFd;
+    ev.events = EPOLLIN;
+    int epoll_fd = epoll_create1(0);
+    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev);
+    int bytes_read = -1;
+    std::string inputStr = "";
+    int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs);
+
+    if (epoll_ret == -1) {
+        close(mGnssFd);
+        return;
+    }
+    while (true) {
+        memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
+        bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
+        if (bytes_read <= 0) {
+            break;
+        }
+        s_buffer_ += std::string(inputBuffer, bytes_read);
+    }
+    close(mGnssFd);
+
+    // Trim end of file mark(\n\n\n\n).
+    auto pos = s_buffer_.find("\n\n\n\n");
+    if (pos != std::string::npos) {
+        inputStr = s_buffer_.substr(0, pos);
+        s_buffer_ = s_buffer_.substr(pos + 4);
+    } else {
+        return;
+    }
+
+    // Cache the injected data.
+    if (ReplayUtils::isGnssRawMeasurement(inputStr)) {
+        data_[CMD_GET_RAWMEASUREMENT] = inputStr;
+    } else if (ReplayUtils::isNMEA(inputStr)) {
+        data_[CMD_GET_LOCATION] = inputStr;
+    }
+}
+
+std::string DeviceFileReader::getLocationData() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    getDataFromDeviceFile(CMD_GET_LOCATION, 20);
+    return data_[CMD_GET_LOCATION];
+}
+
+std::string DeviceFileReader::getGnssRawMeasurementData() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    getDataFromDeviceFile(CMD_GET_RAWMEASUREMENT, 20);
+    return data_[CMD_GET_RAWMEASUREMENT];
+}
+
+DeviceFileReader::DeviceFileReader() {}
+
+DeviceFileReader::~DeviceFileReader() {}
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/common/utils/default/GnssRawMeasurementParser.cpp b/gnss/common/utils/default/GnssRawMeasurementParser.cpp
new file mode 100644
index 0000000..c066229
--- /dev/null
+++ b/gnss/common/utils/default/GnssRawMeasurementParser.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GnssRawMeasurementParser.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+using aidl::android::hardware::gnss::ElapsedRealtime;
+using aidl::android::hardware::gnss::GnssClock;
+using aidl::android::hardware::gnss::GnssConstellationType;
+using aidl::android::hardware::gnss::GnssData;
+using aidl::android::hardware::gnss::GnssMeasurement;
+using aidl::android::hardware::gnss::GnssMultipathIndicator;
+using aidl::android::hardware::gnss::GnssSignalType;
+
+using ParseUtils = ::android::hardware::gnss::common::ParseUtils;
+
+std::unordered_map<std::string, int> GnssRawMeasurementParser::getColumnIdNameMappingFromHeader(
+        const std::string& header) {
+    std::vector<std::string> columnNames;
+    std::unordered_map<std::string, int> columnNameIdMapping;
+    std::string s = header;
+    // Trim left spaces
+    s.erase(s.begin(),
+            std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
+    // Trim right spaces
+    s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); })
+                    .base(),
+            s.end());
+    // Remove comment symbol, start from `Raw`.
+    s = s.substr(s.find("Raw"));
+
+    ParseUtils::splitStr(s, COMMA_SEPARATOR, columnNames);
+    int columnId = 0;
+    for (auto& name : columnNames) {
+        columnNameIdMapping[name] = columnId++;
+    }
+
+    return columnNameIdMapping;
+}
+
+int GnssRawMeasurementParser::getClockFlags(
+        const std::vector<std::string>& rawMeasurementRecordValues,
+        const std::unordered_map<std::string, int>& columnNameIdMapping) {
+    int clockFlags = 0;
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("LeapSecond")].empty()) {
+        clockFlags |= GnssClock::HAS_LEAP_SECOND;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullBiasNanos")].empty()) {
+        clockFlags |= GnssClock::HAS_FULL_BIAS;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasNanos")].empty()) {
+        clockFlags |= GnssClock::HAS_BIAS;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")].empty()) {
+        clockFlags |= GnssClock::HAS_BIAS_UNCERTAINTY;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")].empty()) {
+        clockFlags |= GnssClock::HAS_DRIFT;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftUncertaintyNanosPerSecond")]
+                 .empty()) {
+        clockFlags |= GnssClock::HAS_DRIFT_UNCERTAINTY;
+    }
+    return clockFlags;
+}
+
+int GnssRawMeasurementParser::getElapsedRealtimeFlags(
+        const std::vector<std::string>& rawMeasurementRecordValues,
+        const std::unordered_map<std::string, int>& columnNameIdMapping) {
+    int elapsedRealtimeFlags = ElapsedRealtime::HAS_TIMESTAMP_NS;
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")].empty()) {
+        elapsedRealtimeFlags |= ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS;
+    }
+    return elapsedRealtimeFlags;
+}
+
+int GnssRawMeasurementParser::getRawMeasurementFlags(
+        const std::vector<std::string>& rawMeasurementRecordValues,
+        const std::unordered_map<std::string, int>& columnNameIdMapping) {
+    int rawMeasurementFlags = 0;
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("SnrInDb")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_SNR;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierFrequencyHz")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_FREQUENCY;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierCycles")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_CYCLES;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhase")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhaseUncertainty")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("AgcDb")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasNanos")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasUncertaintyNanos")]
+                 .empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("SatelliteInterSignalBiasNanos")]
+                 .empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at(
+                                            "SatelliteInterSignalBiasUncertaintyNanos")]
+                 .empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY;
+    }
+    // HAS_SATELLITE_PVT and HAS_CORRELATION_VECTOR fields currently not in rawmeasurement
+    // output, need add them later.
+    return rawMeasurementFlags;
+}
+
+GnssConstellationType GnssRawMeasurementParser::getGnssConstellationType(int constellationType) {
+    GnssConstellationType gnssConstellationType =
+            aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
+
+    switch (constellationType) {
+        case 1:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GPS;
+            break;
+        case 2:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::SBAS;
+            break;
+        case 3:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GLONASS;
+            break;
+        case 4:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::QZSS;
+            break;
+        case 5:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::BEIDOU;
+            break;
+        case 6:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GALILEO;
+            break;
+        default:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
+    }
+
+    return gnssConstellationType;
+}
+
+std::unique_ptr<GnssData> GnssRawMeasurementParser::getMeasurementFromStrs(
+        std::string& rawMeasurementStr) {
+    /*
+     * Raw,utcTimeMillis,TimeNanos,LeapSecond,TimeUncertaintyNanos,FullBiasNanos,BiasNanos,
+     * BiasUncertaintyNanos,DriftNanosPerSecond,DriftUncertaintyNanosPerSecond,
+     * HardwareClockDiscontinuityCount,Svid,TimeOffsetNanos,State,ReceivedSvTimeNanos,
+     * ReceivedSvTimeUncertaintyNanos,Cn0DbHz,PseudorangeRateMetersPerSecond,
+     * PseudorangeRateUncertaintyMetersPerSecond,AccumulatedDeltaRangeState,
+     * AccumulatedDeltaRangeMeters,AccumulatedDeltaRangeUncertaintyMeters,CarrierFrequencyHz,
+     * CarrierCycles,CarrierPhase,CarrierPhaseUncertainty,MultipathIndicator,SnrInDb,
+     * ConstellationType,AgcDb,BasebandCn0DbHz,FullInterSignalBiasNanos,
+     * FullInterSignalBiasUncertaintyNanos,SatelliteInterSignalBiasNanos,
+     * SatelliteInterSignalBiasUncertaintyNanos,CodeType,ChipsetElapsedRealtimeNanos
+     */
+    ALOGD("Parsing %zu bytes rawMeasurementStr.", rawMeasurementStr.size());
+    if (rawMeasurementStr.empty()) {
+        return nullptr;
+    }
+    std::vector<std::string> rawMeasurementStrRecords;
+    ParseUtils::splitStr(rawMeasurementStr, LINE_SEPARATOR, rawMeasurementStrRecords);
+    if (rawMeasurementStrRecords.size() <= 1) {
+        ALOGE("Raw GNSS Measurements parser failed. (No records) ");
+        return nullptr;
+    }
+
+    // Get the column name mapping from the header.
+    std::unordered_map<std::string, int> columnNameIdMapping =
+            getColumnIdNameMappingFromHeader(rawMeasurementStrRecords[0]);
+
+    if (columnNameIdMapping.size() < 37 || !ParseUtils::isValidHeader(columnNameIdMapping)) {
+        ALOGE("Raw GNSS Measurements parser failed. (No header or missing columns.) ");
+        return nullptr;
+    }
+
+    // Set GnssClock from 1st record.
+    std::size_t pointer = 1;
+    std::vector<std::string> firstRecordValues;
+    ParseUtils::splitStr(rawMeasurementStrRecords[pointer], COMMA_SEPARATOR, firstRecordValues);
+    GnssClock clock = {
+            .gnssClockFlags = getClockFlags(firstRecordValues, columnNameIdMapping),
+            .timeNs = ParseUtils::tryParseLongLong(
+                    firstRecordValues[columnNameIdMapping.at("TimeNanos")], 0),
+            .fullBiasNs = ParseUtils::tryParseLongLong(
+                    firstRecordValues[columnNameIdMapping.at("FullBiasNanos")], 0),
+            .biasNs = ParseUtils::tryParseDouble(
+                    firstRecordValues[columnNameIdMapping.at("BiasNanos")], 0),
+            .biasUncertaintyNs = ParseUtils::tryParseDouble(
+                    firstRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")], 0),
+            .driftNsps = ParseUtils::tryParseDouble(
+                    firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
+            .driftUncertaintyNsps = ParseUtils::tryParseDouble(
+                    firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
+            .hwClockDiscontinuityCount = ParseUtils::tryParseInt(
+                    firstRecordValues[columnNameIdMapping.at("HardwareClockDiscontinuityCount")],
+                    0)};
+
+    ElapsedRealtime timestamp = {
+            .flags = getElapsedRealtimeFlags(firstRecordValues, columnNameIdMapping),
+            .timestampNs = ParseUtils::tryParseLongLong(
+                    firstRecordValues[columnNameIdMapping.at("ChipsetElapsedRealtimeNanos")]),
+            .timeUncertaintyNs = ParseUtils::tryParseDouble(
+                    firstRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")], 0)};
+
+    std::vector<GnssMeasurement> measurementsVec;
+    for (pointer = 1; pointer < rawMeasurementStrRecords.size(); pointer++) {
+        std::vector<std::string> rawMeasurementValues;
+        std::string line = rawMeasurementStrRecords[pointer];
+        ParseUtils::splitStr(line, COMMA_SEPARATOR, rawMeasurementValues);
+        GnssSignalType signalType = {
+                .constellation = getGnssConstellationType(ParseUtils::tryParseInt(
+                        rawMeasurementValues[columnNameIdMapping.at("ConstellationType")], 0)),
+                .carrierFrequencyHz = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("CarrierFrequencyHz")], 0),
+                .codeType = rawMeasurementValues[columnNameIdMapping.at("CodeType")],
+        };
+        GnssMeasurement measurement = {
+                .flags = getRawMeasurementFlags(rawMeasurementValues, columnNameIdMapping),
+                .svid = ParseUtils::tryParseInt(
+                        rawMeasurementValues[columnNameIdMapping.at("Svid")], 0),
+                .signalType = signalType,
+                .receivedSvTimeInNs = ParseUtils::tryParseLongLong(
+                        rawMeasurementValues[columnNameIdMapping.at("ReceivedSvTimeNanos")], 0),
+                .receivedSvTimeUncertaintyInNs =
+                        ParseUtils::tryParseLongLong(rawMeasurementValues[columnNameIdMapping.at(
+                                                             "ReceivedSvTimeUncertaintyNanos")],
+                                                     0),
+                .antennaCN0DbHz = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("Cn0DbHz")], 0),
+                .basebandCN0DbHz = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("BasebandCn0DbHz")], 0),
+                .agcLevelDb = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("AgcDb")], 0),
+                .pseudorangeRateMps =
+                        ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
+                                                           "PseudorangeRateMetersPerSecond")],
+                                                   0),
+                .pseudorangeRateUncertaintyMps = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at(
+                                "PseudorangeRateUncertaintyMetersPerSecond")],
+                        0),
+                .accumulatedDeltaRangeState = ParseUtils::tryParseInt(
+                        rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeState")],
+                        0),
+                .accumulatedDeltaRangeM = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeMeters")],
+                        0),
+                .accumulatedDeltaRangeUncertaintyM = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at(
+                                "AccumulatedDeltaRangeUncertaintyMeters")],
+                        0),
+                .multipathIndicator = GnssMultipathIndicator::UNKNOWN,  // Not in GnssLogger yet.
+                .state = ParseUtils::tryParseInt(
+                        rawMeasurementValues[columnNameIdMapping.at("State")], 0),
+                .fullInterSignalBiasNs = ParseUtils::tryParseDouble(rawMeasurementValues[31], 0),
+                .fullInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("FullInterSignalBiasNanos")],
+                        0),
+                .satelliteInterSignalBiasNs =
+                        ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
+                                                           "SatelliteInterSignalBiasNanos")],
+                                                   0),
+                .satelliteInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at(
+                                "SatelliteInterSignalBiasUncertaintyNanos")],
+                        0),
+                .satellitePvt = {},
+                .correlationVectors = {}};
+        measurementsVec.push_back(measurement);
+    }
+
+    GnssData gnssData = {
+            .measurements = measurementsVec, .clock = clock, .elapsedRealtime = timestamp};
+    return std::make_unique<GnssData>(gnssData);
+}
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/common/utils/default/GnssReplayUtils.cpp b/gnss/common/utils/default/GnssReplayUtils.cpp
new file mode 100644
index 0000000..e3f4ff8
--- /dev/null
+++ b/gnss/common/utils/default/GnssReplayUtils.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GnssReplayUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+std::string ReplayUtils::getGnssPath() {
+    char devname_value[PROPERTY_VALUE_MAX] = "";
+    if (property_get("debug.location.gnss.devname", devname_value, NULL) > 0) {
+        return devname_value;
+    }
+    return GNSS_PATH;
+}
+
+bool ReplayUtils::hasGnssDeviceFile() {
+    struct stat sb;
+    return stat(getGnssPath().c_str(), &sb) != -1;
+}
+
+bool ReplayUtils::isGnssRawMeasurement(const std::string& inputStr) {
+    // TODO: add more logic check to by pass invalid data.
+    return !inputStr.empty() && (inputStr.find("Raw") != std::string::npos);
+}
+
+bool ReplayUtils::isNMEA(const std::string& inputStr) {
+    return !inputStr.empty() && (inputStr.find("$GPRMC,", 0) != std::string::npos ||
+                                 inputStr.find("$GPRMA,", 0) != std::string::npos);
+}
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/common/utils/default/ParseUtils.cpp b/gnss/common/utils/default/ParseUtils.cpp
new file mode 100644
index 0000000..648edf7
--- /dev/null
+++ b/gnss/common/utils/default/ParseUtils.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <ParseUtils.h>
+#include <sstream>
+#include <stdexcept>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+int ParseUtils::tryParseInt(const std::string& s, int defaultVal) {
+    if (s.empty()) {
+        return defaultVal;
+    } else {
+        return std::stoi(s);
+    }
+}
+
+float ParseUtils::tryParsefloat(const std::string& s, float defaultVal) {
+    if (s.empty()) {
+        return defaultVal;
+    } else {
+        return std::stof(s);
+    }
+}
+
+double ParseUtils::tryParseDouble(const std::string& s, double defaultVal) {
+    if (s.empty()) {
+        return defaultVal;
+    } else {
+        return std::stod(s);
+    }
+}
+
+long ParseUtils::tryParseLong(const std::string& s, long defaultVal) {
+    if (s.empty()) {
+        return defaultVal;
+    } else {
+        return std::stol(s);
+    }
+}
+
+long long ParseUtils::tryParseLongLong(const std::string& s, long long defaultVal) {
+    if (s.empty()) {
+        return defaultVal;
+    } else {
+        return std::stoll(s);
+    }
+}
+
+void ParseUtils::splitStr(const std::string& line, const char& delimiter,
+                          std::vector<std::string>& out) {
+    std::istringstream iss(line);
+    std::string item;
+    while (std::getline(iss, item, delimiter)) {
+        out.push_back(item);
+    }
+}
+
+bool ParseUtils::isValidHeader(const std::unordered_map<std::string, int>& columnNameIdMapping) {
+    std::vector<std::string> requiredHeaderColumns = {"Raw",
+                                                      "utcTimeMillis",
+                                                      "TimeNanos",
+                                                      "LeapSecond",
+                                                      "TimeUncertaintyNanos",
+                                                      "FullBiasNanos",
+                                                      "BiasNanos",
+                                                      "BiasUncertaintyNanos",
+                                                      "DriftNanosPerSecond",
+                                                      "DriftUncertaintyNanosPerSecond",
+                                                      "HardwareClockDiscontinuityCount",
+                                                      "Svid",
+                                                      "TimeOffsetNanos",
+                                                      "State",
+                                                      "ReceivedSvTimeNanos",
+                                                      "ReceivedSvTimeUncertaintyNanos",
+                                                      "Cn0DbHz",
+                                                      "PseudorangeRateMetersPerSecond",
+                                                      "PseudorangeRateUncertaintyMetersPerSecond",
+                                                      "AccumulatedDeltaRangeState",
+                                                      "AccumulatedDeltaRangeMeters",
+                                                      "AccumulatedDeltaRangeUncertaintyMeters",
+                                                      "CarrierFrequencyHz",
+                                                      "CarrierCycles",
+                                                      "CarrierPhase",
+                                                      "CarrierPhaseUncertainty",
+                                                      "MultipathIndicator",
+                                                      "SnrInDb",
+                                                      "ConstellationType",
+                                                      "AgcDb",
+                                                      "BasebandCn0DbHz",
+                                                      "FullInterSignalBiasNanos",
+                                                      "FullInterSignalBiasUncertaintyNanos",
+                                                      "SatelliteInterSignalBiasNanos",
+                                                      "SatelliteInterSignalBiasUncertaintyNanos",
+                                                      "CodeType",
+                                                      "ChipsetElapsedRealtimeNanos"};
+
+    for (const auto& columnName : requiredHeaderColumns) {
+        if (columnNameIdMapping.find(columnName) == columnNameIdMapping.end()) {
+            ALOGE("Missing column %s in header.", columnName.c_str());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index 23e39b2..c339e72 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -28,6 +28,7 @@
 using aidl::android::hardware::gnss::ElapsedRealtime;
 using aidl::android::hardware::gnss::GnssClock;
 using aidl::android::hardware::gnss::GnssData;
+using aidl::android::hardware::gnss::GnssLocation;
 using aidl::android::hardware::gnss::GnssMeasurement;
 using aidl::android::hardware::gnss::IGnss;
 using aidl::android::hardware::gnss::IGnssMeasurementCallback;
@@ -196,13 +197,13 @@
     GnssClock clock = {.gnssClockFlags = GnssClock::HAS_FULL_BIAS | GnssClock::HAS_BIAS |
                                          GnssClock::HAS_BIAS_UNCERTAINTY | GnssClock::HAS_DRIFT |
                                          GnssClock::HAS_DRIFT_UNCERTAINTY,
-                       .timeNs = 35854545000000,
-                       .fullBiasNs = -234621900521857520,
-                       .biasNs = 0.2352389998626708984,
-                       .biasUncertaintyNs = 274.989972114563,
-                       .driftNsps = -124.3742360,
-                       .driftUncertaintyNsps = 239.6234285828,
-                       .hwClockDiscontinuityCount = 999};
+                       .timeNs = 2713545000000,
+                       .fullBiasNs = -1226701900521857520,
+                       .biasNs = 0.59689998626708984,
+                       .biasUncertaintyNs = 47514.989972114563,
+                       .driftNsps = -51.757811607455452,
+                       .driftUncertaintyNsps = 310.64968328491528,
+                       .hwClockDiscontinuityCount = 1};
 
     ElapsedRealtime timestamp = {
             .flags = ElapsedRealtime::HAS_TIMESTAMP_NS | ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS,
@@ -232,6 +233,30 @@
     return gnssData;
 }
 
+GnssLocation Utils::getMockLocation() {
+    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 = gMockLatitudeDegrees,
+                             .longitudeDegrees = gMockLongitudeDegrees,
+                             .altitudeMeters = gMockAltitudeMeters,
+                             .speedMetersPerSec = gMockSpeedMetersPerSec,
+                             .bearingDegrees = gMockBearingDegrees,
+                             .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters,
+                             .verticalAccuracyMeters = kMockVerticalAccuracyMeters,
+                             .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
+                             .bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
+                             .timestampMillis = static_cast<int64_t>(
+                                     kMockTimestamp + ::android::elapsedRealtimeNano() / 1e6),
+                             .elapsedRealtime = elapsedRealtime};
+    return location;
+}
+
 V2_0::GnssLocation Utils::getMockLocationV2_0() {
     const V2_0::ElapsedRealtime timestamp = {
             .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
diff --git a/gnss/common/utils/default/include/Constants.h b/gnss/common/utils/default/include/Constants.h
index 22afee1..f205ba6 100644
--- a/gnss/common/utils/default/include/Constants.h
+++ b/gnss/common/utils/default/include/Constants.h
@@ -34,6 +34,18 @@
 const float kGloG1FreqHz = 1602.0 * 1e6;
 const float kIrnssL5FreqHz = 1176.45 * 1e6;
 
+// Location replay constants
+constexpr char GNSS_PATH[] = "/dev/gnss0";
+constexpr int INPUT_BUFFER_SIZE = 256;
+constexpr char CMD_GET_LOCATION[] = "CMD_GET_LOCATION";
+constexpr char CMD_GET_RAWMEASUREMENT[] = "CMD_GET_RAWMEASUREMENT";
+constexpr char LINE_SEPARATOR = '\n';
+constexpr char COMMA_SEPARATOR = ',';
+constexpr char GPGA_RECORD_TAG[] = "$GPGGA";
+constexpr char GPRMC_RECORD_TAG[] = "$GPRMC";
+constexpr double TIMESTAMP_EPSILON = 0.001;
+constexpr int MIN_COL_NUM = 13;
+
 }  // namespace common
 }  // namespace gnss
 }  // namespace hardware
diff --git a/gnss/common/utils/default/include/DeviceFileReader.h b/gnss/common/utils/default/include/DeviceFileReader.h
new file mode 100644
index 0000000..c2a5c5f
--- /dev/null
+++ b/gnss/common/utils/default/include/DeviceFileReader.h
@@ -0,0 +1,53 @@
+
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef android_hardware_gnss_common_default_DeviceFileReader_H_
+#define android_hardware_gnss_common_default_DeviceFileReader_H_
+
+#include <log/log.h>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include "Constants.h"
+#include "GnssReplayUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+class DeviceFileReader {
+  public:
+    static DeviceFileReader& Instance() {
+        static DeviceFileReader reader;
+        return reader;
+    }
+    std::string getLocationData();
+    std::string getGnssRawMeasurementData();
+    void getDataFromDeviceFile(const std::string& command, int mMinIntervalMs);
+
+  private:
+    DeviceFileReader();
+    ~DeviceFileReader();
+    std::unordered_map<std::string, std::string> data_;
+    std::string s_buffer_;
+    std::mutex mMutex;
+};
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_common_default_DeviceFileReader_H_
\ No newline at end of file
diff --git a/gnss/common/utils/default/include/GnssRawMeasurementParser.h b/gnss/common/utils/default/include/GnssRawMeasurementParser.h
new file mode 100644
index 0000000..7d6b4ef
--- /dev/null
+++ b/gnss/common/utils/default/include/GnssRawMeasurementParser.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_common_default_GnssRawMeasurementParser_H_
+#define android_hardware_gnss_common_default_GnssRawMeasurementParser_H_
+
+#include <aidl/android/hardware/gnss/BnGnss.h>
+#include <log/log.h>
+#include <utils/SystemClock.h>
+#include <string>
+#include <unordered_map>
+
+#include "Constants.h"
+#include "ParseUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct GnssRawMeasurementParser {
+    static std::unique_ptr<aidl::android::hardware::gnss::GnssData> getMeasurementFromStrs(
+            std::string& rawMeasurementStr);
+    static int getClockFlags(const std::vector<std::string>& rawMeasurementRecordValues,
+                             const std::unordered_map<std::string, int>& columnNameIdMapping);
+    static int getElapsedRealtimeFlags(
+            const std::vector<std::string>& rawMeasurementRecordValues,
+            const std::unordered_map<std::string, int>& columnNameIdMapping);
+    static int getRawMeasurementFlags(
+            const std::vector<std::string>& rawMeasurementRecordValues,
+            const std::unordered_map<std::string, int>& columnNameIdMapping);
+    static std::unordered_map<std::string, int> getColumnIdNameMappingFromHeader(
+            const std::string& header);
+    static aidl::android::hardware::gnss::GnssConstellationType getGnssConstellationType(
+            int constellationType);
+};
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_common_default_GnssRawMeasurementParser_H_
\ No newline at end of file
diff --git a/gnss/common/utils/default/include/GnssReplayUtils.h b/gnss/common/utils/default/include/GnssReplayUtils.h
new file mode 100644
index 0000000..32c0e58
--- /dev/null
+++ b/gnss/common/utils/default/include/GnssReplayUtils.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_common_GnssReplayUtils_H_
+#define android_hardware_gnss_common_GnssReplayUtils_H_
+
+#include <cutils/properties.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <log/log.h>
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <chrono>
+#include <string>
+#include <thread>
+
+#include "Constants.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct ReplayUtils {
+    static std::string getGnssPath();
+
+    static std::string getDataFromDeviceFile(const std::string& command, int mMinIntervalMs);
+
+    static bool hasGnssDeviceFile();
+
+    static bool isGnssRawMeasurement(const std::string& inputStr);
+
+    static bool isNMEA(const std::string& inputStr);
+};
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_common_GnssReplayUtils_H_
diff --git a/gnss/common/utils/default/include/NmeaFixInfo.h b/gnss/common/utils/default/include/NmeaFixInfo.h
index c96eece..5c27045 100644
--- a/gnss/common/utils/default/include/NmeaFixInfo.h
+++ b/gnss/common/utils/default/include/NmeaFixInfo.h
@@ -27,13 +27,6 @@
 namespace gnss {
 namespace common {
 
-constexpr char GPGA_RECORD_TAG[] = "$GPGGA";
-constexpr char GPRMC_RECORD_TAG[] = "$GPRMC";
-constexpr char LINE_SEPARATOR = '\n';
-constexpr char COMMA_SEPARATOR = ',';
-constexpr double TIMESTAMP_EPSILON = 0.001;
-constexpr int MIN_COL_NUM = 13;
-
 /** Helper class to parse and store the GNSS fix details information. */
 class NmeaFixInfo {
   private:
diff --git a/gnss/common/utils/default/include/ParseUtils.h b/gnss/common/utils/default/include/ParseUtils.h
new file mode 100644
index 0000000..3a56313
--- /dev/null
+++ b/gnss/common/utils/default/include/ParseUtils.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_common_default_ParseUtils_H_
+#define android_hardware_gnss_common_default_ParseUtils_H_
+
+#include <log/log.h>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct ParseUtils {
+    static int tryParseInt(const std::string& s, int defaultVal = 0);
+    static float tryParsefloat(const std::string& s, float defaultVal = 0.0);
+    static double tryParseDouble(const std::string& s, double defaultVal = 0.0);
+    static long tryParseLong(const std::string& s, long defaultVal = 0);
+    static long long tryParseLongLong(const std::string& s, long long defaultVal = 0);
+    static void splitStr(const std::string& line, const char& delimiter,
+                         std::vector<std::string>& out);
+    static bool isValidHeader(const std::unordered_map<std::string, int>& columnNameIdMapping);
+};
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_common_default_ParseUtils_H_
\ No newline at end of file
diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h
index 43772ce..4500ee6 100644
--- a/gnss/common/utils/default/include/Utils.h
+++ b/gnss/common/utils/default/include/Utils.h
@@ -17,6 +17,7 @@
 #ifndef android_hardware_gnss_common_default_Utils_H_
 #define android_hardware_gnss_common_default_Utils_H_
 
+#include <aidl/android/hardware/gnss/BnGnss.h>
 #include <aidl/android/hardware/gnss/BnGnssMeasurementInterface.h>
 #include <android/hardware/gnss/1.0/IGnss.h>
 #include <android/hardware/gnss/2.0/IGnss.h>
@@ -34,6 +35,7 @@
             const bool enableCorrVecOutputs);
     static V2_0::IGnssMeasurementCallback::GnssData getMockMeasurementV2_0();
     static V2_1::IGnssMeasurementCallback::GnssData getMockMeasurementV2_1();
+    static aidl::android::hardware::gnss::GnssLocation getMockLocation();
     static V2_0::GnssLocation getMockLocationV2_0();
     static V1_0::GnssLocation getMockLocationV1_0();
     static hidl_vec<V2_1::IGnssCallback::GnssSvInfo> getMockSvInfoListV2_1();
diff --git a/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
index 48cab99..c5a186b 100644
--- a/gnss/common/utils/default/include/v2_1/GnssTemplate.h
+++ b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
@@ -30,11 +30,13 @@
 
 #include <cutils/properties.h>
 
+#include "DeviceFileReader.h"
 #include "GnssAntennaInfo.h"
 #include "GnssConfiguration.h"
 #include "GnssDebug.h"
 #include "GnssMeasurement.h"
 #include "GnssMeasurementCorrections.h"
+#include "GnssReplayUtils.h"
 #include "MockLocation.h"
 #include "NmeaFixInfo.h"
 #include "Utils.h"
@@ -44,6 +46,7 @@
 constexpr int INPUT_BUFFER_SIZE = 128;
 constexpr char CMD_GET_LOCATION[] = "CMD_GET_LOCATION";
 constexpr char GNSS_PATH[] = "/dev/gnss0";
+constexpr int TTFF_MILLIS = 2200;
 
 template <class T_IGnss>
 struct GnssTemplate : public T_IGnss {
@@ -129,6 +132,7 @@
     std::atomic<bool> mHardwareModeChecked;
     std::atomic<int> mGnssFd;
     std::thread mThread;
+    std::atomic<bool> mFirstFixReceived;
 
     mutable std::mutex mMutex;
     virtual hidl_vec<V2_1::IGnssCallback::GnssSvInfo> filterBlocklistedSatellitesV2_1(
@@ -150,7 +154,8 @@
     : mMinIntervalMs(1000),
       mGnssConfiguration{new V2_1::implementation::GnssConfiguration()},
       mHardwareModeChecked(false),
-      mGnssFd(-1) {}
+      mGnssFd(-1),
+      mFirstFixReceived(false) {}
 
 template <class T_IGnss>
 GnssTemplate<T_IGnss>::~GnssTemplate() {
@@ -159,52 +164,9 @@
 
 template <class T_IGnss>
 std::unique_ptr<V2_0::GnssLocation> GnssTemplate<T_IGnss>::getLocationFromHW() {
-    char inputBuffer[INPUT_BUFFER_SIZE];
-    if (!mHardwareModeChecked) {
-        // default using gnss0
-        const char * gnss_dev_path = GNSS_PATH;
-        char devname_value[PROPERTY_VALUE_MAX] = "";
-        if (property_get("debug.location.gnss.devname", devname_value, NULL) > 0) {
-            gnss_dev_path = devname_value;
-            ALOGD("using %s instead of the default %s", gnss_dev_path, GNSS_PATH);
-        }
-
-        mGnssFd = open(gnss_dev_path, O_RDWR | O_NONBLOCK);
-        if (mGnssFd == -1) {
-            ALOGW("Failed to open %s errno: %d", gnss_dev_path, errno);
-        }
-        mHardwareModeChecked = true;
-    }
-
-    if (mGnssFd == -1) {
-        return nullptr;
-    }
-
-    int bytes_write = write(mGnssFd, CMD_GET_LOCATION, strlen(CMD_GET_LOCATION));
-    if (bytes_write <= 0) {
-        return nullptr;
-    }
-
-    struct epoll_event ev, events[1];
-    ev.data.fd = mGnssFd;
-    ev.events = EPOLLIN;
-    int epoll_fd = epoll_create1(0);
-    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev);
-    int bytes_read = -1;
-    std::string inputStr = "";
-    int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs);
-
-    if (epoll_ret == -1) {
-        return nullptr;
-    }
-    while (true) {
-        memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
-        bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
-        if (bytes_read <= 0) {
-            break;
-        }
-        inputStr += std::string(inputBuffer, bytes_read);
-    }
+    mHardwareModeChecked = true;
+    std::string inputStr =
+            ::android::hardware::gnss::common::DeviceFileReader::Instance().getLocationData();
     return NmeaFixInfo::getLocationFromInputStr(inputStr);
 }
 
@@ -218,6 +180,12 @@
     mIsActive = true;
     this->reportGnssStatusValue(V1_0::IGnssCallback::GnssStatusValue::SESSION_BEGIN);
     mThread = std::thread([this]() {
+        auto svStatus = filterBlocklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1());
+        this->reportSvStatus(svStatus);
+        if (!mFirstFixReceived) {
+            std::this_thread::sleep_for(std::chrono::milliseconds(TTFF_MILLIS));
+            mFirstFixReceived = true;
+        }
         while (mIsActive == true) {
             auto svStatus = filterBlocklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1());
             this->reportSvStatus(svStatus);
@@ -320,7 +288,7 @@
 
 template <class T_IGnss>
 Return<void> GnssTemplate<T_IGnss>::deleteAidingData(V1_0::IGnss::GnssAidingData) {
-    // TODO implement
+    mFirstFixReceived = false;
     return Void();
 }
 
@@ -555,7 +523,7 @@
     using Capabilities = V2_1::IGnssCallback::Capabilities;
     const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS |
                               Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST |
-                              Capabilities::ANTENNA_INFO;
+                              Capabilities::ANTENNA_INFO | Capabilities::NAV_MESSAGES;
     auto ret = sGnssCallback_2_1->gnssSetCapabilitiesCb_2_1(capabilities);
     if (!ret.isOk()) {
         ALOGE("%s: Unable to invoke callback", __func__);
diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp
index 9c84e80..be22ff6 100644
--- a/gnss/common/utils/vts/Utils.cpp
+++ b/gnss/common/utils/vts/Utils.cpp
@@ -24,12 +24,10 @@
 namespace gnss {
 namespace common {
 
-using GnssConstellationType_V1_0 = V1_0::GnssConstellationType;
-using GnssConstellationType_V2_0 = V2_0::GnssConstellationType;
-
+using namespace measurement_corrections::V1_0;
 using V1_0::GnssLocationFlags;
 
-void Utils::checkLocation(const GnssLocation& location, bool check_speed,
+void Utils::checkLocation(const V1_0::GnssLocation& location, bool check_speed,
                           bool check_more_accuracies) {
     EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
     EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
@@ -96,7 +94,7 @@
     EXPECT_GT(location.timestamp, 1.48e12);
 }
 
-const MeasurementCorrections_1_0 Utils::getMockMeasurementCorrections() {
+const MeasurementCorrections Utils::getMockMeasurementCorrections() {
     ReflectingPlane reflectingPlane = {
             .latitudeDegrees = 37.4220039,
             .longitudeDegrees = -122.0840991,
@@ -104,12 +102,12 @@
             .azimuthDegrees = 203.0,
     };
 
-    SingleSatCorrection_V1_0 singleSatCorrection1 = {
+    SingleSatCorrection singleSatCorrection1 = {
             .singleSatCorrectionFlags = GnssSingleSatCorrectionFlags::HAS_SAT_IS_LOS_PROBABILITY |
                                         GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH |
                                         GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH_UNC |
                                         GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE,
-            .constellation = GnssConstellationType_V1_0::GPS,
+            .constellation = V1_0::GnssConstellationType::GPS,
             .svid = 12,
             .carrierFrequencyHz = 1.59975e+09,
             .probSatIsLos = 0.50001,
@@ -117,11 +115,11 @@
             .excessPathLengthUncertaintyMeters = 25.5,
             .reflectingPlane = reflectingPlane,
     };
-    SingleSatCorrection_V1_0 singleSatCorrection2 = {
+    SingleSatCorrection singleSatCorrection2 = {
             .singleSatCorrectionFlags = GnssSingleSatCorrectionFlags::HAS_SAT_IS_LOS_PROBABILITY |
                                         GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH |
                                         GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH_UNC,
-            .constellation = GnssConstellationType_V1_0::GPS,
+            .constellation = V1_0::GnssConstellationType::GPS,
             .svid = 9,
             .carrierFrequencyHz = 1.59975e+09,
             .probSatIsLos = 0.873,
@@ -129,9 +127,9 @@
             .excessPathLengthUncertaintyMeters = 10.0,
     };
 
-    hidl_vec<SingleSatCorrection_V1_0> singleSatCorrections = {singleSatCorrection1,
-                                                               singleSatCorrection2};
-    MeasurementCorrections_1_0 mockCorrections = {
+    hidl_vec<SingleSatCorrection> singleSatCorrections = {singleSatCorrection1,
+                                                          singleSatCorrection2};
+    MeasurementCorrections mockCorrections = {
             .latitudeDegrees = 37.4219999,
             .longitudeDegrees = -122.0840575,
             .altitudeMeters = 30.60062531,
@@ -143,25 +141,26 @@
     return mockCorrections;
 }
 
-const MeasurementCorrections_1_1 Utils::getMockMeasurementCorrections_1_1() {
-    MeasurementCorrections_1_0 mockCorrections_1_0 = getMockMeasurementCorrections();
+const measurement_corrections::V1_1::MeasurementCorrections
+Utils::getMockMeasurementCorrections_1_1() {
+    MeasurementCorrections mockCorrections_1_0 = getMockMeasurementCorrections();
 
-    SingleSatCorrection_V1_1 singleSatCorrection1 = {
+    measurement_corrections::V1_1::SingleSatCorrection singleSatCorrection1 = {
             .v1_0 = mockCorrections_1_0.satCorrections[0],
-            .constellation = GnssConstellationType_V2_0::IRNSS,
+            .constellation = V2_0::GnssConstellationType::IRNSS,
     };
-    SingleSatCorrection_V1_1 singleSatCorrection2 = {
+    measurement_corrections::V1_1::SingleSatCorrection singleSatCorrection2 = {
             .v1_0 = mockCorrections_1_0.satCorrections[1],
-            .constellation = GnssConstellationType_V2_0::IRNSS,
+            .constellation = V2_0::GnssConstellationType::IRNSS,
     };
 
-    mockCorrections_1_0.satCorrections[0].constellation = GnssConstellationType_V1_0::UNKNOWN;
-    mockCorrections_1_0.satCorrections[1].constellation = GnssConstellationType_V1_0::UNKNOWN;
+    mockCorrections_1_0.satCorrections[0].constellation = V1_0::GnssConstellationType::UNKNOWN;
+    mockCorrections_1_0.satCorrections[1].constellation = V1_0::GnssConstellationType::UNKNOWN;
 
-    hidl_vec<SingleSatCorrection_V1_1> singleSatCorrections = {singleSatCorrection1,
-                                                               singleSatCorrection2};
+    hidl_vec<measurement_corrections::V1_1::SingleSatCorrection> singleSatCorrections = {
+            singleSatCorrection1, singleSatCorrection2};
 
-    MeasurementCorrections_1_1 mockCorrections_1_1 = {
+    measurement_corrections::V1_1::MeasurementCorrections mockCorrections_1_1 = {
             .v1_0 = mockCorrections_1_0,
             .hasEnvironmentBearing = true,
             .environmentBearingDegrees = 45.0,
@@ -177,22 +176,22 @@
  * GnssConstellationType_1_0 type constellation. For constellations that do not have
  * an equivalent value, maps to GnssConstellationType_1_0::UNKNOWN
  */
-GnssConstellationType_1_0 Utils::mapConstellationType(GnssConstellationType_2_0 constellation) {
+V1_0::GnssConstellationType Utils::mapConstellationType(V2_0::GnssConstellationType constellation) {
     switch (constellation) {
-        case GnssConstellationType_2_0::GPS:
-            return GnssConstellationType_1_0::GPS;
-        case GnssConstellationType_2_0::SBAS:
-            return GnssConstellationType_1_0::SBAS;
-        case GnssConstellationType_2_0::GLONASS:
-            return GnssConstellationType_1_0::GLONASS;
-        case GnssConstellationType_2_0::QZSS:
-            return GnssConstellationType_1_0::QZSS;
-        case GnssConstellationType_2_0::BEIDOU:
-            return GnssConstellationType_1_0::BEIDOU;
-        case GnssConstellationType_2_0::GALILEO:
-            return GnssConstellationType_1_0::GALILEO;
+        case V2_0::GnssConstellationType::GPS:
+            return V1_0::GnssConstellationType::GPS;
+        case V2_0::GnssConstellationType::SBAS:
+            return V1_0::GnssConstellationType::SBAS;
+        case V2_0::GnssConstellationType::GLONASS:
+            return V1_0::GnssConstellationType::GLONASS;
+        case V2_0::GnssConstellationType::QZSS:
+            return V1_0::GnssConstellationType::QZSS;
+        case V2_0::GnssConstellationType::BEIDOU:
+            return V1_0::GnssConstellationType::BEIDOU;
+        case V2_0::GnssConstellationType::GALILEO:
+            return V1_0::GnssConstellationType::GALILEO;
         default:
-            return GnssConstellationType_1_0::UNKNOWN;
+            return V1_0::GnssConstellationType::UNKNOWN;
     }
 }
 
diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h
index a4aad80..91c1167 100644
--- a/gnss/common/utils/vts/include/Utils.h
+++ b/gnss/common/utils/vts/include/Utils.h
@@ -22,33 +22,21 @@
 #include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
 #include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
 
-using GnssConstellationType_1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
-using GnssConstellationType_2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
-using GnssLocation = ::android::hardware::gnss::V1_0::GnssLocation;
-using namespace android::hardware::gnss::measurement_corrections::V1_0;
-
-using MeasurementCorrections_1_0 =
-        android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
-using MeasurementCorrections_1_1 =
-        android::hardware::gnss::measurement_corrections::V1_1::MeasurementCorrections;
-
-using SingleSatCorrection_V1_0 =
-        android::hardware::gnss::measurement_corrections::V1_0::SingleSatCorrection;
-using SingleSatCorrection_V1_1 =
-        android::hardware::gnss::measurement_corrections::V1_1::SingleSatCorrection;
-
 namespace android {
 namespace hardware {
 namespace gnss {
 namespace common {
 
 struct Utils {
-    static void checkLocation(const GnssLocation& location, bool check_speed,
+    static void checkLocation(const V1_0::GnssLocation& location, bool check_speed,
                               bool check_more_accuracies);
-    static const MeasurementCorrections_1_0 getMockMeasurementCorrections();
-    static const MeasurementCorrections_1_1 getMockMeasurementCorrections_1_1();
+    static const measurement_corrections::V1_0::MeasurementCorrections
+    getMockMeasurementCorrections();
+    static const measurement_corrections::V1_1::MeasurementCorrections
+    getMockMeasurementCorrections_1_1();
 
-    static GnssConstellationType_1_0 mapConstellationType(GnssConstellationType_2_0 constellation);
+    static V1_0::GnssConstellationType mapConstellationType(
+            V2_0::GnssConstellationType constellation);
 
     static bool isAutomotiveDevice();
 };
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index b23d4a7..69ee498 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -15,7 +15,7 @@
         enabled: true,
         support_system_process: true,
     },
-    vndk_use_version: "2",
+    vndk_use_version: "3",
     srcs: [
         "android/hardware/graphics/common/*.aidl",
     ],
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BlendMode.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BlendMode.aidl
index deafdfa..1c19381 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BlendMode.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BlendMode.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BufferUsage.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BufferUsage.aidl
index 58eefc4..b4ef451 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BufferUsage.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BufferUsage.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ChromaSiting.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ChromaSiting.aidl
index 7ca4dfa..7f0d734 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ChromaSiting.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ChromaSiting.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ColorTransform.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ColorTransform.aidl
new file mode 100644
index 0000000..255a42f
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ColorTransform.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="int") @VintfStability
+enum ColorTransform {
+  IDENTITY = 0,
+  ARBITRARY_MATRIX = 1,
+  VALUE_INVERSE = 2,
+  GRAYSCALE = 3,
+  CORRECT_PROTANOPIA = 4,
+  CORRECT_DEUTERANOPIA = 5,
+  CORRECT_TRITANOPIA = 6,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Compression.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Compression.aidl
index 06e40a0..5b76376 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Compression.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Compression.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Cta861_3.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Cta861_3.aidl
index d4af501..fbe4b2a 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Cta861_3.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Cta861_3.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl
index 43d7f84..3d97cff 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ExtendableType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ExtendableType.aidl
index 6fcb794..3ada312 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ExtendableType.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ExtendableType.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/FRect.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/FRect.aidl
new file mode 100644
index 0000000..cb8190b
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/FRect.aidl
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable FRect {
+  float left;
+  float top;
+  float right;
+  float bottom;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBuffer.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBuffer.aidl
index 72222e1..4d8f78d 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBuffer.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBuffer.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBufferDescription.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBufferDescription.aidl
index 232e023..4955049 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBufferDescription.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBufferDescription.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Hdr.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Hdr.aidl
new file mode 100644
index 0000000..0320a66
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Hdr.aidl
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="int") @VintfStability
+enum Hdr {
+  DOLBY_VISION = 1,
+  HDR10 = 2,
+  HLG = 3,
+  HDR10_PLUS = 4,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Interlaced.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Interlaced.aidl
index 26674c9..30b4e03 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Interlaced.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Interlaced.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
index e5f0470..512fecb 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
@@ -47,4 +63,5 @@
   STENCIL_8 = 53,
   YCBCR_P010 = 54,
   HSV_888 = 55,
+  R_8 = 56,
 }
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayout.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayout.aidl
index 8bca42f..75fac9f 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayout.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayout.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponent.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponent.aidl
index f5a649c..20c0a0b 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponent.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponent.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponentType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
index 7ff8d76..2f7d414 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Point.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Point.aidl
new file mode 100644
index 0000000..3722803
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Point.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable Point {
+  int x;
+  int y;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Rect.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Rect.aidl
index e0ba69b..eb42027 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Rect.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Rect.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Smpte2086.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Smpte2086.aidl
index 5da36f6..2be31d8 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Smpte2086.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Smpte2086.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/StandardMetadataType.aidl
index 34b53a2..150215c 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/StandardMetadataType.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/StandardMetadataType.aidl
@@ -1,14 +1,30 @@
+/**
+ * Copyright (c) 2019,libgralloctypes_helper The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
@@ -40,4 +56,5 @@
   SMPTE2086 = 19,
   CTA861_3 = 20,
   SMPTE2094_40 = 21,
+  SMPTE2094_10 = 22,
 }
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
new file mode 100644
index 0000000..5c3d4cb
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="int") @VintfStability
+enum Transform {
+  FLIP_H = 1,
+  FLIP_V = 2,
+  ROT_90 = 4,
+  ROT_180 = 3,
+  ROT_270 = 7,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/XyColor.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/XyColor.aidl
index d96d0ac..b42de18 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/XyColor.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/XyColor.aidl
@@ -1,14 +1,30 @@
+/**
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/graphics/common/aidl/android/hardware/graphics/common/ColorTransform.aidl b/graphics/common/aidl/android/hardware/graphics/common/ColorTransform.aidl
new file mode 100644
index 0000000..a8784f5
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/ColorTransform.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.graphics.common;
+
+/**
+ * Color transforms that may be applied by hardware composer to the whole
+ * display.
+ */
+@VintfStability
+@Backing(type="int")
+enum ColorTransform {
+    /** Applies no transform to the output color */
+    IDENTITY = 0,
+
+    /** Applies an arbitrary transform defined by a 4x4 affine matrix */
+    ARBITRARY_MATRIX = 1,
+
+    /**
+     * Applies a transform that inverts the value or luminance of the color, but
+     * does not modify hue or saturation
+     */
+    VALUE_INVERSE = 2,
+
+    /** Applies a transform that maps all colors to shades of gray */
+    GRAYSCALE = 3,
+
+    /** Applies a transform which corrects for protanopic color blindness */
+    CORRECT_PROTANOPIA = 4,
+
+    /** Applies a transform which corrects for deuteranopic color blindness */
+    CORRECT_DEUTERANOPIA = 5,
+
+    /** Applies a transform which corrects for tritanopic color blindness */
+    CORRECT_TRITANOPIA = 6
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/FRect.aidl b/graphics/common/aidl/android/hardware/graphics/common/FRect.aidl
new file mode 100644
index 0000000..f9f2b60
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/FRect.aidl
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.common;
+/**
+ * General purpose definition of a rectangle with floating point corners.
+ */
+
+@VintfStability
+parcelable FRect {
+    float left;
+    float top;
+    float right;
+    float bottom;
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Hdr.aidl b/graphics/common/aidl/android/hardware/graphics/common/Hdr.aidl
new file mode 100644
index 0000000..f6d02dd
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/Hdr.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.graphics.common;
+
+/**
+ * Supported HDR formats. Must be kept in sync with equivalents in Display.java.
+ */
+@VintfStability
+@Backing(type="int")
+enum Hdr {
+    /**
+     * Device supports Dolby Vision HDR
+     */
+    DOLBY_VISION = 1,
+    /**
+     * Device supports HDR10
+     */
+    HDR10 = 2,
+    /**
+     * Device supports hybrid log-gamma HDR
+     */
+    HLG = 3,
+    /**
+     * Device supports HDR10+
+     */
+    HDR10_PLUS = 4,
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
index 4e0c5ef..4e891f6 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
@@ -25,7 +25,7 @@
     /**
      * This value may be used in an operation where the format is optional.
      */
-    UNSPECIFIED                        = 0,
+    UNSPECIFIED = 0,
     /**
      * 32-bit format that has 8-bit R, G, B, and A components, in that order,
      * from the lowest memory address to the highest memory address.
@@ -33,7 +33,7 @@
      * The component values are unsigned normalized to the range [0, 1], whose
      * interpretation is defined by the dataspace.
      */
-    RGBA_8888                          = 0x1,
+    RGBA_8888 = 0x1,
 
     /**
      * 32-bit format that has 8-bit R, G, B, and unused components, in that
@@ -42,7 +42,7 @@
      * The component values are unsigned normalized to the range [0, 1], whose
      * interpretation is defined by the dataspace.
      */
-    RGBX_8888                          = 0x2,
+    RGBX_8888 = 0x2,
 
     /**
      * 24-bit format that has 8-bit R, G, and B components, in that order,
@@ -51,7 +51,7 @@
      * The component values are unsigned normalized to the range [0, 1], whose
      * interpretation is defined by the dataspace.
      */
-    RGB_888                            = 0x3,
+    RGB_888 = 0x3,
 
     /**
      * 16-bit packed format that has 5-bit R, 6-bit G, and 5-bit B components,
@@ -61,7 +61,7 @@
      * The component values are unsigned normalized to the range [0, 1], whose
      * interpretation is defined by the dataspace.
      */
-    RGB_565                            = 0x4,
+    RGB_565 = 0x4,
 
     /**
      * 32-bit format that has 8-bit B, G, R, and A components, in that order,
@@ -70,14 +70,14 @@
      * The component values are unsigned normalized to the range [0, 1], whose
      * interpretation is defined by the dataspace.
      */
-    BGRA_8888                          = 0x5,
+    BGRA_8888 = 0x5,
 
     /**
      * Legacy formats deprecated in favor of YCBCR_420_888.
      */
-    YCBCR_422_SP                       = 0x10,  // NV16
-    YCRCB_420_SP                       = 0x11,  // NV21
-    YCBCR_422_I                        = 0x14,  // YUY2
+    YCBCR_422_SP = 0x10, // NV16
+    YCRCB_420_SP = 0x11, // NV21
+    YCBCR_422_I = 0x14, // YUY2
 
     /**
      * 64-bit format that has 16-bit R, G, B, and A components, in that order,
@@ -86,7 +86,7 @@
      * The component values are signed floats, whose interpretation is defined
      * by the dataspace.
      */
-    RGBA_FP16                          = 0x16,
+    RGBA_FP16 = 0x16,
 
     /**
      * RAW16 is a single-channel, 16-bit, little endian format, typically
@@ -129,7 +129,7 @@
      *                                | samples.
      *  Other                         | Unsupported
      */
-    RAW16                              = 0x20,
+    RAW16 = 0x20,
 
     /**
      * BLOB is used to carry task-specific data which does not have a standard
@@ -152,7 +152,7 @@
      *  Dataspace::SENSOR             | Sensor event data.
      *  Other                         | Unsupported
      */
-    BLOB                               = 0x21,
+    BLOB = 0x21,
 
     /**
      * A format indicating that the choice of format is entirely up to the
@@ -168,7 +168,7 @@
      *
      * The interpretation of the component values is defined by the dataspace.
      */
-    IMPLEMENTATION_DEFINED             = 0x22,
+    IMPLEMENTATION_DEFINED = 0x22,
 
     /**
      * This format allows platforms to use an efficient YCbCr/YCrCb 4:2:0
@@ -185,7 +185,7 @@
      *
      * The interpretation of the component values is defined by the dataspace.
      */
-    YCBCR_420_888                      = 0x23,
+    YCBCR_420_888 = 0x23,
 
     /**
      * RAW_OPAQUE is a format for unprocessed raw image buffers coming from an
@@ -207,7 +207,7 @@
      *  Dataspace::ARBITRARY          | Raw image sensor data.
      *  Other                         | Unsupported
      */
-    RAW_OPAQUE                         = 0x24,
+    RAW_OPAQUE = 0x24,
 
     /**
      * RAW10 is a single-channel, 10-bit per pixel, densely packed in each row,
@@ -262,7 +262,7 @@
      *  Dataspace::ARBITRARY          | Raw image sensor data.
      *  Other                         | Unsupported
      */
-    RAW10                              = 0x25,
+    RAW10 = 0x25,
 
     /**
      * RAW12 is a single-channel, 12-bit per pixel, densely packed in each row,
@@ -313,7 +313,7 @@
      *  Dataspace::ARBITRARY          | Raw image sensor data.
      *  Other                         | Unsupported
      */
-    RAW12                              = 0x26,
+    RAW12 = 0x26,
 
     /** 0x27 to 0x2A are reserved for flexible formats */
 
@@ -325,7 +325,7 @@
      * The component values are unsigned normalized to the range [0, 1], whose
      * interpretation is defined by the dataspace.
      */
-    RGBA_1010102                       = 0x2B,
+    RGBA_1010102 = 0x2B,
 
     /**
      * 0x100 - 0x1FF
@@ -357,7 +357,7 @@
      * The component values are unsigned normalized to the range [0, 1], whose
      * interpretation is defined by the dataspace.
      */
-    Y8                                 = 0x20203859,
+    Y8 = 0x20203859,
 
     /**
      * Y16 is a YUV planar format comprised of a WxH Y plane, with each pixel
@@ -384,7 +384,7 @@
      * Dataspace::DEPTH, each pixel is a distance value measured by a depth
      * camera, plus an associated confidence value.
      */
-    Y16                                = 0x20363159,
+    Y16 = 0x20363159,
 
     /**
      * YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed
@@ -413,7 +413,7 @@
      * The component values are unsigned normalized to the range [0, 1], whose
      * interpretation is defined by the dataspace.
      */
-    YV12                               = 0x32315659, // YCrCb 4:2:0 Planar
+    YV12 = 0x32315659, // YCrCb 4:2:0 Planar
 
     /**
      * 16-bit format that has a single 16-bit depth component.
@@ -421,7 +421,7 @@
      * The component values are unsigned normalized to the range [0, 1], whose
      * interpretation is defined by the dataspace.
      */
-    DEPTH_16                           = 0x30,
+    DEPTH_16 = 0x30,
 
     /**
      * 32-bit format that has a single 24-bit depth component and, optionally,
@@ -430,7 +430,7 @@
      * The component values are unsigned normalized to the range [0, 1], whose
      * interpretation is defined by the dataspace.
      */
-    DEPTH_24                           = 0x31,
+    DEPTH_24 = 0x31,
 
     /**
      * 32-bit format that has a 24-bit depth component and an 8-bit stencil
@@ -440,7 +440,7 @@
      * whose interpretation is defined by the dataspace. The stencil values are
      * unsigned integers, whose interpretation is defined by the dataspace.
      */
-    DEPTH_24_STENCIL_8                 = 0x32,
+    DEPTH_24_STENCIL_8 = 0x32,
 
     /**
      * 32-bit format that has a single 32-bit depth component.
@@ -448,7 +448,7 @@
      * The component values are signed floats, whose interpretation is defined
      * by the dataspace.
      */
-    DEPTH_32F                          = 0x33,
+    DEPTH_32F = 0x33,
 
     /**
      * Two-component format that has a 32-bit depth component, an 8-bit stencil
@@ -458,7 +458,7 @@
      * defined by the dataspace. The stencil bits are unsigned integers, whose
      * interpretation is defined by the dataspace.
      */
-    DEPTH_32F_STENCIL_8                = 0x34,
+    DEPTH_32F_STENCIL_8 = 0x34,
 
     /**
      * 8-bit format that has a single 8-bit stencil component.
@@ -466,23 +466,12 @@
      * The component values are unsigned integers, whose interpretation is
      * defined by the dataspace.
      */
-    STENCIL_8                          = 0x35,
+    STENCIL_8 = 0x35,
 
     /**
      * P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane
-     * followed immediately by a Wx(H/2) CbCr plane. Each sample is
-     * represented by a 16-bit little-endian value, with the lower 6 bits set
-     * to zero.
-     *
-     * This format assumes
-     * - an even height
-     * - a vertical stride equal to the height
-     *
-     *   stride_in_bytes = stride * 2
-     *   y_size = stride_in_bytes * height
-     *   cbcr_size = stride_in_bytes * (height / 2)
-     *   cb_offset = y_size
-     *   cr_offset = cb_offset + 2
+     * followed by a Wx(H/2) CbCr plane. Each sample is represented by a 16-bit
+     * little-endian value, with the lower 6 bits set to zero.
      *
      * This format must be accepted by the allocator when used with the
      * following usage flags:
@@ -499,7 +488,7 @@
      * Buffers with this format must be locked with IMapper::lockYCbCr
      * or with IMapper::lock.
      */
-    YCBCR_P010                         = 0x36,
+    YCBCR_P010 = 0x36,
 
     /**
      * 24-bit format that has 8-bit H, S, and V components, in that order,
@@ -507,6 +496,13 @@
      *
      * The component values are unsigned normalized to the range [0, 1], whose
      * interpretation is defined by the dataspace.
-    */
-    HSV_888                            = 0x37,
+     */
+    HSV_888 = 0x37,
+
+    /**
+     * 8 bit format with a single 8-bit component.
+     *
+     * The component values are unsigned normalized to the range [0, 1].
+     */
+    R_8 = 0x38,
 }
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Point.aidl b/graphics/common/aidl/android/hardware/graphics/common/Point.aidl
new file mode 100644
index 0000000..b3ede44
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/Point.aidl
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * General purpose definition of a point.
+ */
+
+@VintfStability
+parcelable Point {
+    int x;
+    int y;
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
index af6045e..7719d6e 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
@@ -344,7 +344,7 @@
     /**
      * Can be used to get or set dynamic HDR metadata specified by SMPTE ST 2094-40:2016.
      *
-     * This metadata is uint8_t byte array.
+     * This metadata is a uint8_t byte array.
      *
      * This is not used in tone mapping until it has been set for the first time.
      *
@@ -353,4 +353,17 @@
      * If this is unset when encoded into a byte stream, the byte stream is empty.
      */
     SMPTE2094_40 = 21,
+
+    /**
+     * Can be used to get or set dynamic HDR metadata specified by SMPTE ST 2094-10:2016.
+     *
+     * This metadata is a uint8_t byte array.
+     *
+     * This is not used in tone mapping until it has been set for the first time.
+     *
+     * When it is encoded into a byte stream, the length of the HDR metadata byte array is written
+     * using 8 bytes in little endian. It is followed by the uint8_t byte array.
+     * If this is unset when encoded into a byte stream, the byte stream is empty.
+     */
+    SMPTE2094_10 = 22,
 }
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Transform.aidl b/graphics/common/aidl/android/hardware/graphics/common/Transform.aidl
new file mode 100644
index 0000000..325816c
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/Transform.aidl
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * Transformation definitions
+ */
+@VintfStability
+@Backing(type="int")
+enum Transform {
+    /**
+     * Horizontal flip. FLIP_H/FLIP_V is applied before ROT_90.
+     */
+    FLIP_H = 1 << 0,
+
+    /**
+     * Vertical flip. FLIP_H/FLIP_V is applied before ROT_90.
+     */
+    FLIP_V = 1 << 1,
+
+    /**
+     * 90 degree clockwise rotation. FLIP_H/FLIP_V is applied before ROT_90.
+     */
+    ROT_90 = 1 << 2,
+
+    /**
+     * Commonly used combinations.
+     */
+    ROT_180 = FLIP_H | FLIP_V,
+    ROT_270 = FLIP_H | FLIP_V | ROT_90,
+}
diff --git a/graphics/composer/2.2/utils/resources/include/composer-resources/2.2/ComposerResources.h b/graphics/composer/2.2/utils/resources/include/composer-resources/2.2/ComposerResources.h
index 33012e9..18a50fe 100644
--- a/graphics/composer/2.2/utils/resources/include/composer-resources/2.2/ComposerResources.h
+++ b/graphics/composer/2.2/utils/resources/include/composer-resources/2.2/ComposerResources.h
@@ -29,6 +29,8 @@
 namespace V2_2 {
 namespace hal {
 
+using V2_1::Display;
+using V2_1::Error;
 using V2_1::hal::ComposerHandleCache;
 using V2_1::hal::ComposerHandleImporter;
 
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
index 5c085cb..4faf84b 100644
--- a/graphics/composer/2.2/utils/vts/Android.bp
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -43,6 +43,8 @@
         "libmath",
         "libnativewindow",
         "librenderengine",
+        "libshaders",
+        "libtonemap",
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@3.0-vts",
         "android.hardware.graphics.mapper@4.0",
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
index f78dda2..2d4cc7d 100644
--- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -60,19 +60,20 @@
 
 void TestRenderEngine::drawLayers() {
     base::unique_fd bufferFence;
-    base::unique_fd readyFence;
 
-    std::vector<const renderengine::LayerSettings*> compositionLayerPointers;
-    compositionLayerPointers.reserve(mCompositionLayers.size());
+    std::vector<renderengine::LayerSettings> compositionLayers;
+    compositionLayers.reserve(mCompositionLayers.size());
     std::transform(mCompositionLayers.begin(), mCompositionLayers.end(),
-                   std::back_insert_iterator(compositionLayerPointers),
-                   [](renderengine::LayerSettings& settings) -> renderengine::LayerSettings* {
-                       return &settings;
+                   std::back_insert_iterator(compositionLayers),
+                   [](renderengine::LayerSettings& settings) -> renderengine::LayerSettings {
+                       return settings;
                    });
     auto texture = std::make_shared<renderengine::ExternalTexture>(
             mGraphicBuffer, *mRenderEngine, renderengine::ExternalTexture::Usage::WRITEABLE);
-    mRenderEngine->drawLayers(mDisplaySettings, compositionLayerPointers, texture, true,
-                              std::move(bufferFence), &readyFence);
+    auto [status, readyFence] = mRenderEngine
+                                        ->drawLayers(mDisplaySettings, compositionLayers, texture,
+                                                     true, std::move(bufferFence))
+                                        .get();
     int fd = readyFence.release();
     if (fd != -1) {
         ASSERT_EQ(0, sync_wait(fd, -1));
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 36f3c00..1e0a329 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -67,6 +67,8 @@
         "android.hardware.graphics.mapper@4.0-vts",
         "libgtest",
         "librenderengine",
+        "libshaders",
+        "libtonemap",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index 7a053f1..e2a0f4d 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -97,7 +97,6 @@
         renderengine::DisplaySettings clientCompositionDisplay;
         clientCompositionDisplay.physicalDisplay = Rect(mDisplayWidth, mDisplayHeight);
         clientCompositionDisplay.clip = clientCompositionDisplay.physicalDisplay;
-        clientCompositionDisplay.clearRegion = Region(clientCompositionDisplay.physicalDisplay);
 
         mTestRenderEngine->initGraphicBuffer(
                 static_cast<uint32_t>(mDisplayWidth), static_cast<uint32_t>(mDisplayHeight), 1,
diff --git a/graphics/composer/2.4/IComposerClient.hal b/graphics/composer/2.4/IComposerClient.hal
index 9e3cf0e..476302f 100644
--- a/graphics/composer/2.4/IComposerClient.hal
+++ b/graphics/composer/2.4/IComposerClient.hal
@@ -305,9 +305,8 @@
      * If the display is internally connected (not through HDMI), and such modes are available,
      * this method should trigger them.
      *
-     * This function should only be called if the display reports support for the corresponding
-     * content type (ContentType::{GRAPHICS, PHOTO, CINEMA, GAME}) from getSupportedContentTypes.
-     * ContentType::NONE is supported by default and can always be set.
+     * This function can be called for a content type even if no support for it is
+     * reported from getSupportedContentTypes.
      *
      * @return error is NONE upon success. Otherwise,
      *     BAD_DISPLAY when an invalid display handle was passed in.
diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp
new file mode 100644
index 0000000..2532a7a
--- /dev/null
+++ b/graphics/composer/aidl/Android.bp
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    // 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.graphics.composer3",
+    host_supported: true,
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    srcs: [
+        "android/hardware/graphics/composer3/*.aidl",
+    ],
+    stability: "vintf",
+    imports: [
+        "android.hardware.graphics.common-V3",
+        "android.hardware.common-V2",
+    ],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+            enabled: false,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
+
+cc_library_headers {
+    name: "android.hardware.graphics.composer3-command-buffer",
+    vendor_available: true,
+    shared_libs: [
+        "android.hardware.graphics.composer3-V1-ndk",
+        "android.hardware.common-V2-ndk",
+        "libbase",
+        "libfmq",
+        "libsync",
+    ],
+    static_libs: [
+        "libaidlcommonsupport",
+    ],
+    export_shared_lib_headers: [
+        "libfmq",
+        "libsync",
+    ],
+    export_include_dirs: ["include"],
+}
+
+cc_test {
+    name: "android.hardware.graphics.composer3-hidl2aidl-asserts",
+    vendor_available: true,
+    srcs: ["android/hardware/graphics/composer3/Hidl2AidlAsserts.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+        "libhidlbase",
+        "android.hardware.graphics.composer3-V1-ndk",
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.4",
+    ],
+}
diff --git a/graphics/composer/aidl/OWNERS b/graphics/composer/aidl/OWNERS
new file mode 100644
index 0000000..9028d9d
--- /dev/null
+++ b/graphics/composer/aidl/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 1075131
+
+# Graphics team
+adyabr@google.com
+alecmouri@google.com
+sumir@google.com
\ No newline at end of file
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Buffer.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Buffer.aidl
new file mode 100644
index 0000000..a33ad23
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Buffer.aidl
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable Buffer {
+  int slot;
+  @nullable android.hardware.common.NativeHandle handle;
+  @nullable ParcelFileDescriptor fence;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl
new file mode 100644
index 0000000..9c49583
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="int") @VintfStability
+enum Capability {
+  INVALID = 0,
+  SIDEBAND_STREAM = 1,
+  SKIP_CLIENT_COLOR_TRANSFORM = 2,
+  PRESENT_FENCE_IS_NOT_RELIABLE = 3,
+  SKIP_VALIDATE = 4,
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl
new file mode 100644
index 0000000..7e47ba8
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ChangedCompositionLayer {
+  long layer;
+  android.hardware.graphics.composer3.Composition composition;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl
new file mode 100644
index 0000000..9a5ca97
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ChangedCompositionTypes {
+  long display;
+  android.hardware.graphics.composer3.ChangedCompositionLayer[] layers;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTarget.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTarget.aidl
new file mode 100644
index 0000000..7632707
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTarget.aidl
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ClientTarget {
+  android.hardware.graphics.composer3.Buffer buffer;
+  android.hardware.graphics.common.Dataspace dataspace;
+  android.hardware.graphics.common.Rect[] damage;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTargetProperty.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTargetProperty.aidl
new file mode 100644
index 0000000..d34d1b0
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTargetProperty.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ClientTargetProperty {
+  android.hardware.graphics.common.PixelFormat pixelFormat;
+  android.hardware.graphics.common.Dataspace dataspace;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl
new file mode 100644
index 0000000..f0fb22e
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ClientTargetPropertyWithNits {
+  long display;
+  android.hardware.graphics.composer3.ClientTargetProperty clientTargetProperty;
+  float whitePointNits;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl
new file mode 100644
index 0000000..480a85c
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ClockMonotonicTimestamp {
+  long timestampNanos;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Color.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Color.aidl
new file mode 100644
index 0000000..7733deb
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Color.aidl
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable Color {
+  byte r;
+  byte g;
+  byte b;
+  byte a;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ColorMode.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ColorMode.aidl
new file mode 100644
index 0000000..53852b6
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ColorMode.aidl
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="int") @VintfStability
+enum ColorMode {
+  NATIVE = 0,
+  STANDARD_BT601_625 = 1,
+  STANDARD_BT601_625_UNADJUSTED = 2,
+  STANDARD_BT601_525 = 3,
+  STANDARD_BT601_525_UNADJUSTED = 4,
+  STANDARD_BT709 = 5,
+  DCI_P3 = 6,
+  SRGB = 7,
+  ADOBE_RGB = 8,
+  DISPLAY_P3 = 9,
+  BT2020 = 10,
+  BT2100_PQ = 11,
+  BT2100_HLG = 12,
+  DISPLAY_BT2020 = 13,
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandError.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandError.aidl
new file mode 100644
index 0000000..103bfdc
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandError.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable CommandError {
+  int commandIndex;
+  int errorCode;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandResultPayload.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandResultPayload.aidl
new file mode 100644
index 0000000..ebbb31e
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandResultPayload.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+union CommandResultPayload {
+  android.hardware.graphics.composer3.CommandError error;
+  android.hardware.graphics.composer3.ChangedCompositionTypes changedCompositionTypes;
+  android.hardware.graphics.composer3.DisplayRequest displayRequest;
+  android.hardware.graphics.composer3.PresentFence presentFence;
+  android.hardware.graphics.composer3.ReleaseFences releaseFences;
+  android.hardware.graphics.composer3.PresentOrValidate presentOrValidateResult;
+  android.hardware.graphics.composer3.ClientTargetPropertyWithNits clientTargetProperty;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Composition.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Composition.aidl
new file mode 100644
index 0000000..d2d8f04
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Composition.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="int") @VintfStability
+enum Composition {
+  INVALID = 0,
+  CLIENT = 1,
+  DEVICE = 2,
+  SOLID_COLOR = 3,
+  CURSOR = 4,
+  SIDEBAND = 5,
+  DISPLAY_DECORATION = 6,
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ContentType.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ContentType.aidl
new file mode 100644
index 0000000..d87b767
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ContentType.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="int") @VintfStability
+enum ContentType {
+  NONE = 0,
+  GRAPHICS = 1,
+  PHOTO = 2,
+  CINEMA = 3,
+  GAME = 4,
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayAttribute.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayAttribute.aidl
new file mode 100644
index 0000000..8454c40
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayAttribute.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="int") @VintfStability
+enum DisplayAttribute {
+  INVALID = 0,
+  WIDTH = 1,
+  HEIGHT = 2,
+  VSYNC_PERIOD = 3,
+  DPI_X = 4,
+  DPI_Y = 5,
+  CONFIG_GROUP = 7,
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
new file mode 100644
index 0000000..9f5342e
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="int") @VintfStability
+enum DisplayCapability {
+  INVALID = 0,
+  SKIP_CLIENT_COLOR_TRANSFORM = 1,
+  DOZE = 2,
+  BRIGHTNESS = 3,
+  PROTECTED_CONTENTS = 4,
+  AUTO_LOW_LATENCY_MODE = 5,
+  SUSPEND = 6,
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl
new file mode 100644
index 0000000..3382633
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable DisplayCommand {
+  long display;
+  android.hardware.graphics.composer3.LayerCommand[] layers;
+  @nullable float[] colorTransformMatrix;
+  @nullable android.hardware.graphics.composer3.ClientTarget clientTarget;
+  @nullable android.hardware.graphics.composer3.Buffer virtualDisplayOutputBuffer;
+  @nullable android.hardware.graphics.composer3.ClockMonotonicTimestamp expectedPresentTime;
+  boolean validateDisplay;
+  boolean acceptDisplayChanges;
+  boolean presentDisplay;
+  boolean presentOrValidateDisplay;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConnectionType.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConnectionType.aidl
new file mode 100644
index 0000000..640f82a
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConnectionType.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="int") @VintfStability
+enum DisplayConnectionType {
+  INTERNAL = 0,
+  EXTERNAL = 1,
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayContentSample.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayContentSample.aidl
new file mode 100644
index 0000000..c624536
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayContentSample.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable DisplayContentSample {
+  long frameCount;
+  long[] sampleComponent0;
+  long[] sampleComponent1;
+  long[] sampleComponent2;
+  long[] sampleComponent3;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayContentSamplingAttributes.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayContentSamplingAttributes.aidl
new file mode 100644
index 0000000..7c6542f
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayContentSamplingAttributes.aidl
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable DisplayContentSamplingAttributes {
+  android.hardware.graphics.common.PixelFormat format;
+  android.hardware.graphics.common.Dataspace dataspace;
+  android.hardware.graphics.composer3.FormatColorComponent componentMask;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayIdentification.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayIdentification.aidl
new file mode 100644
index 0000000..a0cc9b0
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayIdentification.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable DisplayIdentification {
+  byte port;
+  byte[] data;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayRequest.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayRequest.aidl
new file mode 100644
index 0000000..13462ce
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayRequest.aidl
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable DisplayRequest {
+  long display;
+  int mask;
+  android.hardware.graphics.composer3.DisplayRequest.LayerRequest[] layerRequests;
+  const int FLIP_CLIENT_TARGET = 1;
+  const int WRITE_CLIENT_TARGET_TO_OUTPUT = 2;
+  @VintfStability
+  parcelable LayerRequest {
+    long layer;
+    int mask;
+    const int CLEAR_CLIENT_TARGET = 1;
+  }
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/FloatColor.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/FloatColor.aidl
new file mode 100644
index 0000000..faadf57
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/FloatColor.aidl
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable FloatColor {
+  float r;
+  float g;
+  float b;
+  float a;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/FormatColorComponent.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/FormatColorComponent.aidl
new file mode 100644
index 0000000..4b737de
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/FormatColorComponent.aidl
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="byte") @VintfStability
+enum FormatColorComponent {
+  FORMAT_COMPONENT_0 = 1,
+  FORMAT_COMPONENT_1 = 2,
+  FORMAT_COMPONENT_2 = 4,
+  FORMAT_COMPONENT_3 = 8,
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/HdrCapabilities.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/HdrCapabilities.aidl
new file mode 100644
index 0000000..80141d3
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/HdrCapabilities.aidl
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable HdrCapabilities {
+  android.hardware.graphics.common.Hdr[] types;
+  float maxLuminance;
+  float maxAverageLuminance;
+  float minLuminance;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposer.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposer.aidl
new file mode 100644
index 0000000..9abc608
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposer.aidl
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+interface IComposer {
+  android.hardware.graphics.composer3.IComposerClient createClient();
+  String dumpDebugInfo();
+  android.hardware.graphics.composer3.Capability[] getCapabilities();
+  const int EX_NO_RESOURCES = 6;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl
new file mode 100644
index 0000000..f82d02e
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+interface IComposerCallback {
+  void onHotplug(long display, boolean connected);
+  oneway void onRefresh(long display);
+  oneway void onSeamlessPossible(long display);
+  oneway void onVsync(long display, long timestamp, int vsyncPeriodNanos);
+  oneway void onVsyncPeriodTimingChanged(long display, in android.hardware.graphics.composer3.VsyncPeriodChangeTimeline updatedTimeline);
+}
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
new file mode 100644
index 0000000..2d17e0f
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -0,0 +1,84 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+interface IComposerClient {
+  long createLayer(long display, int bufferSlotCount);
+  android.hardware.graphics.composer3.VirtualDisplay createVirtualDisplay(int width, int height, android.hardware.graphics.common.PixelFormat formatHint, int outputBufferSlotCount);
+  void destroyLayer(long display, long layer);
+  void destroyVirtualDisplay(long display);
+  android.hardware.graphics.composer3.CommandResultPayload[] executeCommands(in android.hardware.graphics.composer3.DisplayCommand[] commands);
+  int getActiveConfig(long display);
+  android.hardware.graphics.composer3.ColorMode[] getColorModes(long display);
+  float[] getDataspaceSaturationMatrix(android.hardware.graphics.common.Dataspace dataspace);
+  int getDisplayAttribute(long display, int config, android.hardware.graphics.composer3.DisplayAttribute attribute);
+  android.hardware.graphics.composer3.DisplayCapability[] getDisplayCapabilities(long display);
+  int[] getDisplayConfigs(long display);
+  android.hardware.graphics.composer3.DisplayConnectionType getDisplayConnectionType(long display);
+  android.hardware.graphics.composer3.DisplayIdentification getDisplayIdentificationData(long display);
+  String getDisplayName(long display);
+  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.composer3.HdrCapabilities getHdrCapabilities(long display);
+  int getMaxVirtualDisplayCount();
+  android.hardware.graphics.composer3.PerFrameMetadataKey[] getPerFrameMetadataKeys(long display);
+  android.hardware.graphics.composer3.ReadbackBufferAttributes getReadbackBufferAttributes(long display);
+  @nullable ParcelFileDescriptor getReadbackBufferFence(long display);
+  android.hardware.graphics.composer3.RenderIntent[] getRenderIntents(long display, android.hardware.graphics.composer3.ColorMode mode);
+  android.hardware.graphics.composer3.ContentType[] getSupportedContentTypes(long display);
+  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 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);
+  void setContentType(long display, android.hardware.graphics.composer3.ContentType type);
+  void setDisplayBrightness(long display, float brightness);
+  void setDisplayedContentSamplingEnabled(long display, boolean enable, android.hardware.graphics.composer3.FormatColorComponent componentMask, long maxFrames);
+  void setPowerMode(long display, android.hardware.graphics.composer3.PowerMode mode);
+  void setReadbackBuffer(long display, in android.hardware.common.NativeHandle buffer, in @nullable ParcelFileDescriptor releaseFence);
+  void setVsyncEnabled(long display, boolean enabled);
+  const int EX_BAD_CONFIG = 1;
+  const int EX_BAD_DISPLAY = 2;
+  const int EX_BAD_LAYER = 3;
+  const int EX_BAD_PARAMETER = 4;
+  const int EX_RESERVED = 5;
+  const int EX_NO_RESOURCES = 6;
+  const int EX_NOT_VALIDATED = 7;
+  const int EX_UNSUPPORTED = 8;
+  const int EX_SEAMLESS_NOT_ALLOWED = 9;
+  const int EX_SEAMLESS_NOT_POSSIBLE = 10;
+  const int INVALID_CONFIGURATION = 2147483647;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
new file mode 100644
index 0000000..ab77880
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable LayerCommand {
+  long layer;
+  @nullable android.hardware.graphics.common.Point cursorPosition;
+  @nullable android.hardware.graphics.composer3.Buffer buffer;
+  @nullable android.hardware.graphics.common.Rect[] damage;
+  @nullable android.hardware.graphics.composer3.ParcelableBlendMode blendMode;
+  @nullable android.hardware.graphics.composer3.Color color;
+  @nullable android.hardware.graphics.composer3.FloatColor floatColor;
+  @nullable android.hardware.graphics.composer3.ParcelableComposition composition;
+  @nullable android.hardware.graphics.composer3.ParcelableDataspace dataspace;
+  @nullable android.hardware.graphics.common.Rect displayFrame;
+  @nullable android.hardware.graphics.composer3.PlaneAlpha planeAlpha;
+  @nullable android.hardware.common.NativeHandle sidebandStream;
+  @nullable android.hardware.graphics.common.FRect sourceCrop;
+  @nullable android.hardware.graphics.composer3.ParcelableTransform transform;
+  @nullable android.hardware.graphics.common.Rect[] visibleRegion;
+  @nullable android.hardware.graphics.composer3.ZOrder z;
+  @nullable float[] colorTransform;
+  @nullable android.hardware.graphics.composer3.WhitePointNits whitePointNits;
+  @nullable android.hardware.graphics.composer3.PerFrameMetadata[] perFrameMetadata;
+  @nullable android.hardware.graphics.composer3.PerFrameMetadataBlob[] perFrameMetadataBlob;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableBlendMode.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableBlendMode.aidl
new file mode 100644
index 0000000..f1fee5f
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableBlendMode.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ParcelableBlendMode {
+  android.hardware.graphics.common.BlendMode blendMode;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableComposition.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableComposition.aidl
new file mode 100644
index 0000000..98fbb66
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableComposition.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ParcelableComposition {
+  android.hardware.graphics.composer3.Composition composition;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableDataspace.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableDataspace.aidl
new file mode 100644
index 0000000..76ecf85
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableDataspace.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ParcelableDataspace {
+  android.hardware.graphics.common.Dataspace dataspace;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableTransform.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableTransform.aidl
new file mode 100644
index 0000000..b673656
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableTransform.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ParcelableTransform {
+  android.hardware.graphics.common.Transform transform;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PerFrameMetadata.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PerFrameMetadata.aidl
new file mode 100644
index 0000000..cd1f351
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PerFrameMetadata.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable PerFrameMetadata {
+  android.hardware.graphics.composer3.PerFrameMetadataKey key;
+  float value;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PerFrameMetadataBlob.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PerFrameMetadataBlob.aidl
new file mode 100644
index 0000000..c1e74d9
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PerFrameMetadataBlob.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable PerFrameMetadataBlob {
+  android.hardware.graphics.composer3.PerFrameMetadataKey key;
+  byte[] blob;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PerFrameMetadataKey.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PerFrameMetadataKey.aidl
new file mode 100644
index 0000000..8722f87
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PerFrameMetadataKey.aidl
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="int") @VintfStability
+enum PerFrameMetadataKey {
+  DISPLAY_RED_PRIMARY_X = 0,
+  DISPLAY_RED_PRIMARY_Y = 1,
+  DISPLAY_GREEN_PRIMARY_X = 2,
+  DISPLAY_GREEN_PRIMARY_Y = 3,
+  DISPLAY_BLUE_PRIMARY_X = 4,
+  DISPLAY_BLUE_PRIMARY_Y = 5,
+  WHITE_POINT_X = 6,
+  WHITE_POINT_Y = 7,
+  MAX_LUMINANCE = 8,
+  MIN_LUMINANCE = 9,
+  MAX_CONTENT_LIGHT_LEVEL = 10,
+  MAX_FRAME_AVERAGE_LIGHT_LEVEL = 11,
+  HDR10_PLUS_SEI = 12,
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PlaneAlpha.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PlaneAlpha.aidl
new file mode 100644
index 0000000..c48c2a8
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PlaneAlpha.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable PlaneAlpha {
+  float alpha;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PowerMode.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PowerMode.aidl
new file mode 100644
index 0000000..f587d4d
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PowerMode.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="int") @VintfStability
+enum PowerMode {
+  OFF = 0,
+  DOZE = 1,
+  DOZE_SUSPEND = 3,
+  ON = 2,
+  ON_SUSPEND = 4,
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentFence.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentFence.aidl
new file mode 100644
index 0000000..3bb09cd
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentFence.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable PresentFence {
+  long display;
+  ParcelFileDescriptor fence;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentOrValidate.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentOrValidate.aidl
new file mode 100644
index 0000000..e6ddeba
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentOrValidate.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable PresentOrValidate {
+  long display;
+  android.hardware.graphics.composer3.PresentOrValidate.Result result;
+  @VintfStability
+  enum Result {
+    Validated = 0,
+    Presented = 1,
+  }
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ReadbackBufferAttributes.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ReadbackBufferAttributes.aidl
new file mode 100644
index 0000000..bb51bdc
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ReadbackBufferAttributes.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ReadbackBufferAttributes {
+  android.hardware.graphics.common.PixelFormat format;
+  android.hardware.graphics.common.Dataspace dataspace;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ReleaseFences.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ReleaseFences.aidl
new file mode 100644
index 0000000..d623661
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ReleaseFences.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ReleaseFences {
+  long display;
+  android.hardware.graphics.composer3.ReleaseFences.Layer[] layers;
+  @VintfStability
+  parcelable Layer {
+    long layer;
+    ParcelFileDescriptor fence;
+  }
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/RenderIntent.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/RenderIntent.aidl
new file mode 100644
index 0000000..5670c10
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/RenderIntent.aidl
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="int") @VintfStability
+enum RenderIntent {
+  COLORIMETRIC = 0,
+  ENHANCE = 1,
+  TONE_MAP_COLORIMETRIC = 2,
+  TONE_MAP_ENHANCE = 3,
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VirtualDisplay.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VirtualDisplay.aidl
new file mode 100644
index 0000000..886be2e
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VirtualDisplay.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable VirtualDisplay {
+  long display;
+  android.hardware.graphics.common.PixelFormat format;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VsyncPeriodChangeConstraints.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VsyncPeriodChangeConstraints.aidl
new file mode 100644
index 0000000..df38c11
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VsyncPeriodChangeConstraints.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable VsyncPeriodChangeConstraints {
+  long desiredTimeNanos;
+  boolean seamlessRequired;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VsyncPeriodChangeTimeline.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VsyncPeriodChangeTimeline.aidl
new file mode 100644
index 0000000..9fb3999
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VsyncPeriodChangeTimeline.aidl
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable VsyncPeriodChangeTimeline {
+  long newVsyncAppliedTimeNanos;
+  boolean refreshRequired;
+  long refreshTimeNanos;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/WhitePointNits.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/WhitePointNits.aidl
new file mode 100644
index 0000000..c3925d2
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/WhitePointNits.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable WhitePointNits {
+  float nits;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ZOrder.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ZOrder.aidl
new file mode 100644
index 0000000..ea96ea3
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ZOrder.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable ZOrder {
+  int z;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Buffer.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Buffer.aidl
new file mode 100644
index 0000000..415a9b6
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Buffer.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.common.NativeHandle;
+
+@VintfStability
+parcelable Buffer {
+    /**
+     * Buffer slot in the range [0, bufferSlotCount) where bufferSlotCount is
+     * the parameter used when the layer was created.
+     * @see IComposer.createLayer.
+     * The slot is used as a buffer caching mechanism. When the Buffer.handle
+     * is null, the implementation uses the previous buffer associated with this
+     * slot.
+     */
+    int slot;
+
+    /**
+     * Buffer Handle. Can be null if this is the same buffer that was sent
+     * previously on this slot.
+     */
+    @nullable NativeHandle handle;
+
+    /**
+     * Buffer fence that represents when it is safe to access the buffer.
+     * A null fence indicates that the buffer can be accessed immediately.
+     */
+    @nullable ParcelFileDescriptor fence;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Capability.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Capability.aidl
new file mode 100644
index 0000000..ea619ae
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Capability.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.graphics.composer3;
+
+/**
+ * Optional capabilities which may be supported by some devices. The
+ * particular set of supported capabilities for a given device may be
+ * retrieved using getCapabilities.
+ */
+@VintfStability
+@Backing(type="int")
+enum Capability {
+    INVALID = 0,
+    /**
+     * Specifies that the device supports sideband stream layers, for
+     * which buffer content updates and other synchronization will not be
+     * provided through the usual validate/present cycle and must be
+     * handled by an external implementation-defined mechanism. Only
+     * changes to layer state (such as position, size, etc.) need to be
+     * performed through the validate/present cycle.
+     */
+    SIDEBAND_STREAM = 1,
+    /**
+     * Specifies that the device will apply a color transform even when
+     * either the client or the device has chosen that all layers should
+     * be composed by the client. This will prevent the client from
+     * applying the color transform during its composition step.
+     */
+    SKIP_CLIENT_COLOR_TRANSFORM = 2,
+    /**
+     * Specifies that the present fence must not be used as an accurate
+     * representation of the actual present time of a frame.
+     */
+    PRESENT_FENCE_IS_NOT_RELIABLE = 3,
+    /**
+     * Specifies that a device is able to skip the validateDisplay call before
+     * receiving a call to presentDisplay. The client will always skip
+     * validateDisplay and try to call presentDisplay regardless of the changes
+     * in the properties of the layers. If the device returns anything else than
+     * no error, it will call validateDisplay then presentDisplay again.
+     * For this capability to be worthwhile the device implementation of
+     * presentDisplay should fail as fast as possible in the case a
+     * validateDisplay step is needed.
+     */
+    SKIP_VALIDATE = 4,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl
new file mode 100644
index 0000000..fb25163
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.Composition;
+
+@VintfStability
+parcelable ChangedCompositionLayer {
+    /**
+     * The layer which this commands refers to.
+     * @see IComposer.createLayer
+     */
+    long layer;
+
+    /**
+     * The new composition type.
+     */
+    Composition composition;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl
new file mode 100644
index 0000000..ddd45b7
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.ChangedCompositionLayer;
+import android.hardware.graphics.composer3.Composition;
+
+@VintfStability
+parcelable ChangedCompositionTypes {
+    /**
+     * The display which this commands refers to.
+     * @see IComposer.createDisplay
+     */
+    long display;
+
+    /**
+     * Indicates which layers has composition changes
+     */
+    ChangedCompositionLayer[] layers;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTarget.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTarget.aidl
new file mode 100644
index 0000000..56488d5
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTarget.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.common.Dataspace;
+import android.hardware.graphics.common.Rect;
+import android.hardware.graphics.composer3.Buffer;
+
+@VintfStability
+parcelable ClientTarget {
+    /**
+     * Client target Buffer
+     */
+    Buffer buffer;
+
+    /**
+     * The dataspace of the buffer, as described in LayerCommand.dataspace.
+     */
+    Dataspace dataspace;
+
+    /**
+     * The surface damage regions.
+     */
+    Rect[] damage;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetProperty.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetProperty.aidl
new file mode 100644
index 0000000..b4d5887
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetProperty.aidl
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable ClientTargetProperty {
+    android.hardware.graphics.common.PixelFormat pixelFormat;
+    android.hardware.graphics.common.Dataspace dataspace;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl
new file mode 100644
index 0000000..5037651
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.ClientTargetProperty;
+
+@VintfStability
+parcelable ClientTargetPropertyWithNits {
+    /**
+     * The display which this commands refers to.
+     * @see IComposer.createDisplay
+     */
+    long display;
+
+    /**
+     * The Client target property.
+     */
+    ClientTargetProperty clientTargetProperty;
+
+    /**
+     * The white points nits as described in CommandResultPayload.clientTargetProperty
+     */
+    float whitePointNits;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl
new file mode 100644
index 0000000..0cfd1c4
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+/**
+ * Represents a nanoseconds timestamp in CLOCK_MONOTONIC.
+ */
+@VintfStability
+parcelable ClockMonotonicTimestamp {
+    long timestampNanos;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Color.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Color.aidl
new file mode 100644
index 0000000..979f677
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Color.aidl
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable Color {
+    byte r;
+    byte g;
+    byte b;
+    byte a;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ColorMode.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ColorMode.aidl
new file mode 100644
index 0000000..c13d207
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ColorMode.aidl
@@ -0,0 +1,283 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+@Backing(type="int")
+enum ColorMode {
+    /**
+     * DEFAULT is the "native" gamut of the display.
+     * White Point: Vendor/OEM defined
+     * Panel Gamma: Vendor/OEM defined (typically 2.2)
+     * Rendering Intent: Vendor/OEM defined (typically 'enhanced')
+     */
+    NATIVE = 0,
+    /**
+     * STANDARD_BT601_625 corresponds with display
+     * settings that implement the ITU-R Recommendation BT.601
+     * or Rec 601. Using 625 line version
+     * Rendering Intent: Colorimetric
+     * Primaries:
+     *                  x       y
+     *  green           0.290   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     *
+     *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+     *  for RGB conversion from the one purely determined by the primaries
+     *  to minimize the color shift into RGB space that uses BT.709
+     *  primaries.
+     *
+     * Gamma Correction (GC):
+     *
+     *  if Vlinear < 0.018
+     *    Vnonlinear = 4.500 * Vlinear
+     *  else
+     *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+     */
+    STANDARD_BT601_625 = 1,
+    /**
+     * Primaries:
+     *                  x       y
+     *  green           0.290   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     *
+     *  Use the unadjusted KR = 0.222, KB = 0.071 luminance interpretation
+     *  for RGB conversion.
+     *
+     * Gamma Correction (GC):
+     *
+     *  if Vlinear < 0.018
+     *    Vnonlinear = 4.500 * Vlinear
+     *  else
+     *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+     */
+    STANDARD_BT601_625_UNADJUSTED = 2,
+    /**
+     * Primaries:
+     *                  x       y
+     *  green           0.310   0.595
+     *  blue            0.155   0.070
+     *  red             0.630   0.340
+     *  white (D65)     0.3127  0.3290
+     *
+     *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+     *  for RGB conversion from the one purely determined by the primaries
+     *  to minimize the color shift into RGB space that uses BT.709
+     *  primaries.
+     *
+     * Gamma Correction (GC):
+     *
+     *  if Vlinear < 0.018
+     *    Vnonlinear = 4.500 * Vlinear
+     *  else
+     *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+     */
+    STANDARD_BT601_525 = 3,
+    /**
+     * Primaries:
+     *                  x       y
+     *  green           0.310   0.595
+     *  blue            0.155   0.070
+     *  red             0.630   0.340
+     *  white (D65)     0.3127  0.3290
+     *
+     *  Use the unadjusted KR = 0.212, KB = 0.087 luminance interpretation
+     *  for RGB conversion (as in SMPTE 240M).
+     *
+     * Gamma Correction (GC):
+     *
+     *  if Vlinear < 0.018
+     *    Vnonlinear = 4.500 * Vlinear
+     *  else
+     *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+     */
+    STANDARD_BT601_525_UNADJUSTED = 4,
+    /**
+     * REC709 corresponds with display settings that implement
+     * the ITU-R Recommendation BT.709 / Rec. 709 for high-definition television.
+     * Rendering Intent: Colorimetric
+     * Primaries:
+     *                  x       y
+     *  green           0.300   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     *
+     * HDTV REC709 Inverse Gamma Correction (IGC): V represents normalized
+     * (with [0 to 1] range) value of R, G, or B.
+     *
+     *  if Vnonlinear < 0.081
+     *    Vlinear = Vnonlinear / 4.5
+     *  else
+     *    Vlinear = ((Vnonlinear + 0.099) / 1.099) ^ (1/0.45)
+     *
+     * HDTV REC709 Gamma Correction (GC):
+     *
+     *  if Vlinear < 0.018
+     *    Vnonlinear = 4.5 * Vlinear
+     *  else
+     *    Vnonlinear = 1.099 * (Vlinear) ^ 0.45 – 0.099
+     */
+    STANDARD_BT709 = 5,
+    /**
+     * DCI_P3 corresponds with display settings that implement
+     * SMPTE EG 432-1 and SMPTE RP 431-2
+     * Rendering Intent: Colorimetric
+     * Primaries:
+     *                  x       y
+     *  green           0.265   0.690
+     *  blue            0.150   0.060
+     *  red             0.680   0.320
+     *  white (D65)     0.3127  0.3290
+     *
+     * Gamma: 2.6
+     */
+    DCI_P3 = 6,
+    /**
+     * SRGB corresponds with display settings that implement
+     * the sRGB color space. Uses the same primaries as ITU-R Recommendation
+     * BT.709
+     * Rendering Intent: Colorimetric
+     * Primaries:
+     *                  x       y
+     *  green           0.300   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     *
+     * PC/Internet (sRGB) Inverse Gamma Correction (IGC):
+     *
+     *  if Vnonlinear ≤ 0.03928
+     *    Vlinear = Vnonlinear / 12.92
+     *  else
+     *    Vlinear = ((Vnonlinear + 0.055)/1.055) ^ 2.4
+     *
+     * PC/Internet (sRGB) Gamma Correction (GC):
+     *
+     *  if Vlinear ≤ 0.0031308
+     *    Vnonlinear = 12.92 * Vlinear
+     *  else
+     *    Vnonlinear = 1.055 * (Vlinear)^(1/2.4) – 0.055
+     */
+    SRGB = 7,
+    /**
+     * ADOBE_RGB corresponds with the RGB color space developed
+     * by Adobe Systems, Inc. in 1998.
+     * Rendering Intent: Colorimetric
+     * Primaries:
+     *                  x       y
+     *  green           0.210   0.710
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     *
+     * Gamma: 2.2
+     */
+    ADOBE_RGB = 8,
+    /**
+     * DISPLAY_P3 is a color space that uses the DCI_P3 primaries,
+     * the D65 white point and the SRGB transfer functions.
+     * Rendering Intent: Colorimetric
+     * Primaries:
+     *                  x       y
+     *  green           0.265   0.690
+     *  blue            0.150   0.060
+     *  red             0.680   0.320
+     *  white (D65)     0.3127  0.3290
+     *
+     * PC/Internet (sRGB) Gamma Correction (GC):
+     *
+     *  if Vlinear ≤ 0.0030186
+     *    Vnonlinear = 12.92 * Vlinear
+     *  else
+     *    Vnonlinear = 1.055 * (Vlinear)^(1/2.4) – 0.055
+     *
+     * Note: In most cases sRGB transfer function will be fine.
+     */
+    DISPLAY_P3 = 9,
+    /**
+     * BT2020 corresponds with display settings that implement the ITU-R
+     * Recommendation BT.2020 / Rec. 2020 for UHDTV.
+     *
+     * Primaries:
+     *                  x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * Inverse Gamma Correction (IGC): V represents normalized (with [0 to 1]
+     * range) value of R, G, or B.
+     *
+     *  if Vnonlinear < b * 4.5
+     *    Vlinear = Vnonlinear / 4.5
+     *  else
+     *    Vlinear = ((Vnonlinear + (a - 1)) / a) ^ (1/0.45)
+     *
+     * Gamma Correction (GC):
+     *
+     *  if Vlinear < b
+     *    Vnonlinear = 4.5 * Vlinear
+     *  else
+     *    Vnonlinear = a * Vlinear ^ 0.45 - (a - 1)
+     *
+     * where
+     *
+     *   a = 1.09929682680944, b = 0.018053968510807
+     *
+     * For practical purposes, these a/b values can be used instead
+     *
+     *   a = 1.099, b = 0.018 for 10-bit display systems
+     *   a = 1.0993, b = 0.0181 for 12-bit display systems
+     */
+    BT2020 = 10,
+    /**
+     * BT2100_PQ and BT2100_HLG correspond with display settings that
+     * implement the ITU-R Recommendation BT.2100 / Rec. 2100 for HDR TV.
+     *
+     * Primaries:
+     *                  x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * For BT2100_PQ, the transfer function is Perceptual Quantizer (PQ). For
+     * BT2100_HLG, the transfer function is Hybrid Log-Gamma (HLG).
+     */
+    BT2100_PQ = 11,
+    BT2100_HLG = 12,
+    /**
+     * DISPLAY_BT2020 corresponds with display settings that implement the ITU-R
+     * Recommendation BT.2020 / Rec. 2020 for UHDTV, but specifies an SRGB
+     * transfer function.
+     *
+     * Primaries:
+     *                  x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * Transfer Function is sRGB
+     */
+    DISPLAY_BT2020 = 13,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/CommandError.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandError.aidl
new file mode 100644
index 0000000..ea48600
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandError.aidl
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable CommandError {
+    /**
+     * The index in the command payload array.
+     */
+    int commandIndex;
+    /**
+     * The error generated by the command. Can be one of the IComposerClient.EX_*
+     */
+    int errorCode;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl
new file mode 100644
index 0000000..f2de68e
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.ChangedCompositionTypes;
+import android.hardware.graphics.composer3.ClientTargetPropertyWithNits;
+import android.hardware.graphics.composer3.CommandError;
+import android.hardware.graphics.composer3.DisplayRequest;
+import android.hardware.graphics.composer3.PresentFence;
+import android.hardware.graphics.composer3.PresentOrValidate;
+import android.hardware.graphics.composer3.ReleaseFences;
+
+@VintfStability
+union CommandResultPayload {
+    /**
+     * Indicates an error generated by a command.
+     */
+    CommandError error;
+
+    /**
+     * Sets the layers for which the device requires a different composition
+     * type than had been set prior to the last call to VALIDATE_DISPLAY. The
+     * client must either update its state with these types and call
+     * ACCEPT_DISPLAY_CHANGES, or must set new types and attempt to validate
+     * the display again.
+     */
+    ChangedCompositionTypes changedCompositionTypes;
+
+    /**
+     * Sets the display requests and the layer requests required for the last
+     * validated configuration.
+     *
+     * Display requests provide information about how the client must handle
+     * the client target. Layer requests provide information about how the
+     * client must handle an individual layer.
+     */
+    DisplayRequest displayRequest;
+
+    /**
+     * Sets the present fence as a result of PRESENT_DISPLAY. For physical
+     * displays, this fence must be signaled at the vsync when the result
+     * of composition of this frame starts to appear (for video-mode panels)
+     * or starts to transfer to panel memory (for command-mode panels). For
+     * virtual displays, this fence must be signaled when writes to the output
+     * buffer have completed and it is safe to read from it.
+     */
+    PresentFence presentFence;
+
+    /**
+     * Sets the release fences for device layers on this display which will
+     * receive new buffer contents this frame.
+     *
+     * A release fence is a file descriptor referring to a sync fence object
+     * which must be signaled after the device has finished reading from the
+     * buffer presented in the prior frame. This indicates that it is safe to
+     * start writing to the buffer again. If a given layer's fence is not
+     * returned from this function, it must be assumed that the buffer
+     * presented on the previous frame is ready to be written.
+     *
+     * The fences returned by this function must be unique for each layer
+     * (even if they point to the same underlying sync object).
+     *
+     */
+    ReleaseFences releaseFences;
+
+    /**
+     * Sets the state of PRESENT_OR_VALIDATE_DISPLAY command.
+     */
+    PresentOrValidate presentOrValidateResult;
+
+    /**
+     * The white point parameter describes the intended white point of the client target buffer.
+     * When client composition blends both HDR and SDR content, the client must composite to the
+     * brightness space as specified by the hardware composer. This is so that adjusting the real
+     * display brightness may be applied atomically with compensating the client target output. For
+     * instance, client-compositing a list of SDR layers requires dimming the brightness space of
+     * the SDR buffers when an HDR layer is simultaneously device-composited.
+     */
+    ClientTargetPropertyWithNits clientTargetProperty;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Composition.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Composition.aidl
new file mode 100644
index 0000000..803de06
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Composition.aidl
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+/**
+ * Possible composition types for a given layer.
+ */
+@VintfStability
+@Backing(type="int")
+enum Composition {
+    INVALID = 0,
+    /**
+     * The client must composite this layer into the client target buffer
+     * (provided to the device through setClientTarget).
+     *
+     * The device must not request any composition type changes for layers
+     * of this type.
+     */
+    CLIENT = 1,
+    /**
+     * The device must handle the composition of this layer through a
+     * hardware overlay or other similar means.
+     *
+     * Upon validateDisplay, the device may request a change from this
+     * type to CLIENT.
+     */
+    DEVICE = 2,
+    /**
+     * The device must render this layer using the color set through
+     * setLayerColor. If this functionality is not supported on a layer
+     * that the client sets to SOLID_COLOR, the device must request that
+     * the composition type of that layer is changed to CLIENT upon the
+     * next call to validateDisplay.
+     *
+     * Upon validateDisplay, the device may request a change from this
+     * type to CLIENT.
+     */
+    SOLID_COLOR = 3,
+    /**
+     * Similar to DEVICE, but the position of this layer may also be set
+     * asynchronously through setCursorPosition. If this functionality is
+     * not supported on a layer that the client sets to CURSOR, the device
+     * must request that the composition type of that layer is changed to
+     * CLIENT upon the next call to validateDisplay.
+     *
+     * Upon validateDisplay, the device may request a change from this
+     * type to either DEVICE or CLIENT.  Changing to DEVICE will prevent
+     * the use of setCursorPosition but still permit the device to
+     * composite the layer.
+     */
+    CURSOR = 4,
+    /**
+     * The device must handle the composition of this layer, as well as
+     * its buffer updates and content synchronization. Only supported on
+     * devices which provide Capability.SIDEBAND_STREAM.
+     *
+     * Upon validateDisplay, the device may request a change from this
+     * type to either DEVICE or CLIENT, but it is unlikely that content
+     * will display correctly in these cases.
+     */
+    SIDEBAND = 5,
+    /**
+     * A display decoration layer contains a buffer which is used to provide
+     * anti-aliasing on the cutout region/rounded corners on the top and
+     * bottom of a display.
+     *
+     * Pixels in the buffer with an alpha of 0 (transparent) will show the
+     * content underneath, and pixels with a max alpha value will be rendered in
+     * black. An alpha in between will show the underlying content blended with
+     * black.
+     *
+     * Upon validateDisplay, the device may request a change from this type
+     * to either DEVICE or CLIENT.
+     */
+    DISPLAY_DECORATION = 6,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ContentType.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ContentType.aidl
new file mode 100644
index 0000000..470064a
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ContentType.aidl
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+@Backing(type="int")
+enum ContentType {
+    NONE = 0,
+    /**
+     * These modes correspond to those found in the HDMI 1.4 specification.
+     */
+    GRAPHICS = 1,
+    PHOTO = 2,
+    CINEMA = 3,
+    GAME = 4,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayAttribute.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayAttribute.aidl
new file mode 100644
index 0000000..bf66785
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayAttribute.aidl
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.DisplayAttribute;
+
+/**
+ * Display attributes queryable through getDisplayAttribute.
+ */
+@VintfStability
+@Backing(type="int")
+enum DisplayAttribute {
+    INVALID = 0,
+    /**
+     * Dimensions in pixels
+     */
+    WIDTH = 1,
+    HEIGHT = 2,
+    /**
+     * Vsync period in nanoseconds
+     */
+    VSYNC_PERIOD = 3,
+    /**
+     * Dots per thousand inches (DPI * 1000). Scaling by 1000 allows these
+     * numbers to be stored in an int32_t without losing too much
+     * precision. If the DPI for a configuration is unavailable or is
+     * considered unreliable, the device may return UNSUPPORTED instead.
+     */
+    DPI_X = 4,
+    DPI_Y = 5,
+
+    // 6 is reserved for legacy interfaces
+
+    /**
+     * The configuration group ID (as int32_t) this config is associated to.
+     * Switching between configurations within the same group may be done seamlessly
+     * in some conditions via setActiveConfigWithConstraints. Configurations which
+     * share the same config group are similar in all attributes except for the
+     * vsync period.
+     */
+    CONFIG_GROUP = 7,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
new file mode 100644
index 0000000..eacf106
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.DisplayCapability;
+
+/**
+ * Required capabilities which are supported by the display. The
+ * particular set of supported capabilities for a given display may be
+ * retrieved using getDisplayCapabilities.
+ */
+@VintfStability
+@Backing(type="int")
+enum DisplayCapability {
+    INVALID = 0,
+    /**
+     * Indicates that the display must apply a color transform even when
+     * either the client or the device has chosen that all layers should
+     * be composed by the client. This prevents the client from applying
+     * the color transform during its composition step.
+     * If getDisplayCapabilities is supported, the global capability
+     * SKIP_CLIENT_COLOR_TRANSFORM is ignored.
+     * If getDisplayCapabilities is not supported, and the global capability
+     * SKIP_CLIENT_COLOR_TRANSFORM is returned by getCapabilities,
+     * then all displays must be treated as having
+     * SKIP_CLIENT_COLOR_TRANSFORM.
+     */
+    SKIP_CLIENT_COLOR_TRANSFORM = 1,
+    /**
+     * Indicates that the display supports PowerMode.DOZE and
+     * potentially PowerMode.DOZE_SUSPEND if DisplayCapability.SUSPEND is also
+     * supported. DOZE_SUSPEND may not provide any benefit
+     * over DOZE (see the definition of PowerMode for more information),
+     * but if both DOZE and DOZE_SUSPEND are no different from
+     * PowerMode.ON, the device must not claim support.
+     * Must be returned by getDisplayCapabilities when getDozeSupport
+     * indicates the display supports PowerMode.DOZE and
+     * PowerMode.DOZE_SUSPEND.
+     */
+    DOZE = 2,
+    /**
+     * Indicates that the display supports brightness operations.
+     */
+    BRIGHTNESS = 3,
+    /**
+     * Indicates that the display supports protected contents.
+     * When returned, hardware composer must be able to accept client target
+     * with protected buffers.
+     */
+    PROTECTED_CONTENTS = 4,
+    /**
+     * Indicates that both the composer HAL implementation and the given display
+     * support a low latency mode, such as HDMI 2.1 Auto Low Latency Mode.
+     */
+    AUTO_LOW_LATENCY_MODE = 5,
+    /**
+     * Indicates that the display supports PowerMode.ON_SUSPEND.
+     * If PowerMode.ON_SUSPEND is no different from PowerMode.ON, the device must not
+     * claim support.
+     * If the display supports DisplayCapability.DOZE and DisplayCapability.SUSPEND, then
+     * PowerMode.ON_SUSPEND and PowerMode.DOZE_SUSPEND must be supported.
+     */
+    SUSPEND = 6,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl
new file mode 100644
index 0000000..18461ad
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl
@@ -0,0 +1,162 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.Buffer;
+import android.hardware.graphics.composer3.ClientTarget;
+import android.hardware.graphics.composer3.ClockMonotonicTimestamp;
+import android.hardware.graphics.composer3.LayerCommand;
+
+@VintfStability
+parcelable DisplayCommand {
+    /**
+     * The display which this commands refers to.
+     * @see IComposer.createDisplay
+     */
+    long display;
+
+    /**
+     * Sets layer commands for this display.
+     * @see LayerCommand.
+     */
+    LayerCommand[] layers;
+
+    /**
+     * Sets a color transform which will be applied after composition.
+     *
+     * If the device is not capable of either using the matrix to
+     * apply the desired color transform, it must force all layers to client
+     * composition during VALIDATE_DISPLAY.
+     *
+     * If Capability.SKIP_CLIENT_COLOR_TRANSFORM is present, then
+     * the client must never apply the color transform during client
+     * composition, even if all layers are being composed by the client.
+     *
+     * The matrix provided is an affine color transformation of the following
+     * form:
+     *
+     * |r.r r.g r.b 0|
+     * |g.r g.g g.b 0|
+     * |b.r b.g b.b 0|
+     * |Tr  Tg  Tb  1|
+     *
+     * This matrix must be provided in row-major form:
+     *
+     * {r.r, r.g, r.b, 0, g.r, ...}.
+     *
+     * Given a matrix of this form and an input color [R_in, G_in, B_in], the
+     * output color [R_out, G_out, B_out] will be:
+     *
+     * R_out = R_in * r.r + G_in * g.r + B_in * b.r + Tr
+     * G_out = R_in * r.g + G_in * g.g + B_in * b.g + Tg
+     * B_out = R_in * r.b + G_in * g.b + B_in * b.b + Tb
+     *
+     */
+    @nullable float[] colorTransformMatrix;
+
+    /**
+     * Sets the buffer handle which will receive the output of client
+     * composition.  Layers marked as Composition.CLIENT must be composited
+     * into this buffer prior to the call to PRESENT_DISPLAY, and layers not
+     * marked as Composition.CLIENT must be composited with this buffer by
+     * the device.
+     *
+     * The buffer handle provided may be empty if no layers are being
+     * composited by the client. This must not result in an error (unless an
+     * invalid display handle is also provided).
+     *
+     * Also provides a file descriptor referring to an acquire sync fence
+     * object, which must be signaled when it is safe to read from the client
+     * target buffer.  If it is already safe to read from this buffer, an
+     * empty handle may be passed instead.
+     *
+     * For more about dataspaces, see SET_LAYER_DATASPACE.
+     *
+     * The damage parameter describes a surface damage region as defined in
+     * the description of SET_LAYER_SURFACE_DAMAGE.
+     *
+     * Will be called before PRESENT_DISPLAY if any of the layers are marked
+     * as Composition.CLIENT. If no layers are so marked, then it is not
+     * necessary to call this function. It is not necessary to call
+     * validateDisplay after changing the target through this function.
+     */
+    @nullable ClientTarget clientTarget;
+
+    /**
+     * Sets the output buffer for a virtual display. That is, the buffer to
+     * which the composition result will be written.
+     *
+     * Also provides a file descriptor referring to a release sync fence
+     * object, which must be signaled when it is safe to write to the output
+     * buffer. If it is already safe to write to the output buffer, an empty
+     * handle may be passed instead.
+     *
+     * Must be called at least once before PRESENT_DISPLAY, but does not have
+     * any interaction with layer state or display validation.
+     */
+    @nullable Buffer virtualDisplayOutputBuffer;
+
+    /**
+     * Sets the expected present time to present the current content on screen.
+     * The implementation should try to present the display as close as possible
+     * to the given expectedPresentTime. If expectedPresentTime is 0, the
+     * implementation should present the display as soon as possible.
+     */
+    @nullable ClockMonotonicTimestamp expectedPresentTime;
+
+    /**
+     * Instructs the device to inspect all of the layer state and determine if
+     * there are any composition type changes necessary before presenting the
+     * display. Permitted changes are described in the definition of
+     * Composition above.
+     */
+    boolean validateDisplay;
+
+    /**
+     * Accepts the changes required by the device from the previous
+     * validateDisplay call (which may be queried using
+     * getChangedCompositionTypes) and revalidates the display. This function
+     * is equivalent to requesting the changed types from
+     * getChangedCompositionTypes, setting those types on the corresponding
+     * layers, and then calling validateDisplay again.
+     *
+     * After this call it must be valid to present this display. Calling this
+     * after validateDisplay returns 0 changes must succeed with NONE, but
+     * must have no other effect.
+     */
+    boolean acceptDisplayChanges;
+
+    /**
+     * Presents the current display contents on the screen (or in the case of
+     * virtual displays, into the output buffer).
+     *
+     * Prior to calling this function, the display must be successfully
+     * validated with validateDisplay. Note that setLayerBuffer and
+     * setLayerSurfaceDamage specifically do not count as layer state, so if
+     * there are no other changes to the layer state (or to the buffer's
+     * properties as described in setLayerBuffer), then it is safe to call
+     * this function without first validating the display.
+     */
+    boolean presentDisplay;
+
+    /**
+     * Presents the current display contents on the screen (or in the case of
+     * virtual displays, into the output buffer) if validate can be skipped,
+     * or perform a VALIDATE_DISPLAY action instead.
+     */
+    boolean presentOrValidateDisplay;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConnectionType.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConnectionType.aidl
new file mode 100644
index 0000000..80333cb
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConnectionType.aidl
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+@Backing(type="int")
+enum DisplayConnectionType {
+    /**
+     * Display is connected through internal port, e.g. DSI, eDP.
+     */
+    INTERNAL = 0,
+    /**
+     * Display is connected through external port, e.g. HDMI, DisplayPort.
+     */
+    EXTERNAL = 1,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayContentSample.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayContentSample.aidl
new file mode 100644
index 0000000..9457d99
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayContentSample.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.graphics.composer3;
+
+/**
+ * Output parameters for IComposerClient.getDisplayedContentSample
+ */
+@VintfStability
+parcelable DisplayContentSample {
+    /**
+     * The number of frames represented by this sample.
+     */
+    long frameCount;
+    /**
+     * A histogram counting how many times a pixel of a given value was displayed
+     * onscreen for FORMAT_COMPONENT_0. The buckets of the histogram are evenly
+     * weighted, the number of buckets is device specific. eg, for RGBA_8888,
+     * if sampleComponent0 is {10, 6, 4, 1} this means that 10 red pixels were
+     * displayed onscreen in range 0x00->0x3F, 6 red pixels were displayed
+     * onscreen in range 0x40->0x7F, etc.
+     */
+    long[] sampleComponent0;
+    /**
+     * The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_1.
+     */
+    long[] sampleComponent1;
+    /**
+     * The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_2.
+     */
+    long[] sampleComponent2;
+    /**
+     * The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_3.
+     */
+    long[] sampleComponent3;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayContentSamplingAttributes.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayContentSamplingAttributes.aidl
new file mode 100644
index 0000000..82f6b72
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayContentSamplingAttributes.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.FormatColorComponent;
+
+/**
+ * Output parameters for IComposerClient.getDisplayedContentSamplingAttributes
+ */
+@VintfStability
+parcelable DisplayContentSamplingAttributes {
+    /**
+     * The format of the sampled pixels.
+     */
+    android.hardware.graphics.common.PixelFormat format;
+    /**
+     * The dataspace of the sampled pixels.
+     */
+    android.hardware.graphics.common.Dataspace dataspace;
+    /**
+     * The mask of which components can be sampled.
+     */
+    FormatColorComponent componentMask;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayIdentification.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayIdentification.aidl
new file mode 100644
index 0000000..03ef8e6
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayIdentification.aidl
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+/**
+ * Output parameters for IComposerClient.getDisplayIdentificationData
+ */
+@VintfStability
+parcelable DisplayIdentification {
+    /**
+     * The connector to which the display is connected.
+     */
+    byte port;
+    /**
+     * The EDID 1.3 blob identifying the display.
+     */
+    byte[] data;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayRequest.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayRequest.aidl
new file mode 100644
index 0000000..27fe1e6
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayRequest.aidl
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable DisplayRequest {
+    /**
+     * Instructs the client to provide a new client target buffer, even if
+     * no layers are marked for client composition.
+     */
+    const int FLIP_CLIENT_TARGET = 1 << 0;
+
+    /**
+     * Instructs the client to write the result of client composition
+     * directly into the virtual display output buffer. If any of the
+     * layers are not marked as Composition.CLIENT or the given display
+     * is not a virtual display, this request has no effect.
+     */
+    const int WRITE_CLIENT_TARGET_TO_OUTPUT = 1 << 1;
+
+    /**
+     * The display which this commands refers to.
+     * @see IComposer.createDisplay
+     */
+    long display;
+
+    /**
+     * The display requests for the current validated state. This must be a
+     * bitwise-or of the constants in `DisplayRequest`.
+     */
+    int mask;
+
+    @VintfStability
+    parcelable LayerRequest {
+        /**
+         * The client must clear its target with transparent pixels where
+         * this layer would be. The client may ignore this request if the
+         * layer must be blended.
+         */
+        const int CLEAR_CLIENT_TARGET = 1 << 0;
+
+        /**
+         * The layer which this commands refers to.
+         * @see IComposer.createLayer
+         */
+        long layer;
+        /**
+         * The layer requests for the current validated state. This must be a
+         * bitwise-or of the constants in `LayerRequest`.
+         */
+        int mask;
+    }
+
+    /**
+     * The layer requests for the current validated state.
+     */
+    LayerRequest[] layerRequests;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/FloatColor.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/FloatColor.aidl
new file mode 100644
index 0000000..a0a1d4b
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/FloatColor.aidl
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+/**
+ * Color representation as a floating point number in the range [0.0 - 1.0]
+ */
+
+@VintfStability
+parcelable FloatColor {
+    float r;
+    float g;
+    float b;
+    float a;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/FormatColorComponent.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/FormatColorComponent.aidl
new file mode 100644
index 0000000..cc8f424
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/FormatColorComponent.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+@Backing(type="byte")
+enum FormatColorComponent {
+    /*
+     * The first component  (eg, for RGBA_8888, this is R)
+     */
+    FORMAT_COMPONENT_0 = 1 << 0,
+    /*
+     * The second component (eg, for RGBA_8888, this is G)
+     */
+    FORMAT_COMPONENT_1 = 1 << 1,
+    /*
+     * The third component  (eg, for RGBA_8888, this is B)
+     */
+    FORMAT_COMPONENT_2 = 1 << 2,
+    /*
+     * The fourth component (eg, for RGBA_8888, this is A)
+     */
+    FORMAT_COMPONENT_3 = 1 << 3,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/HdrCapabilities.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/HdrCapabilities.aidl
new file mode 100644
index 0000000..3fb55ba
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/HdrCapabilities.aidl
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+/**
+ * Output parameters for IComposerClient.getHdrCapabilities
+ *
+ * @param types is an array of HDR types, may have 0 elements if the
+ *         display is not HDR-capable.
+ * @param maxLuminance is the desired content maximum luminance for this
+ *         display in cd/m^2.
+ * @param maxAverageLuminance - the desired content maximum frame-average
+ *         luminance for this display in cd/m^2.
+ * @param minLuminance is the desired content minimum luminance for this
+ *         display in cd/m^2.
+ */
+@VintfStability
+parcelable HdrCapabilities {
+    android.hardware.graphics.common.Hdr[] types;
+    float maxLuminance;
+    float maxAverageLuminance;
+    float minLuminance;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Hidl2AidlAsserts.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/Hidl2AidlAsserts.cpp
new file mode 100644
index 0000000..d34b405
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Hidl2AidlAsserts.cpp
@@ -0,0 +1,354 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "aidl/android/hardware/graphics/common/BlendMode.h"
+#include "aidl/android/hardware/graphics/common/FRect.h"
+#include "aidl/android/hardware/graphics/common/Rect.h"
+#include "aidl/android/hardware/graphics/composer3/Capability.h"
+#include "aidl/android/hardware/graphics/composer3/ClientTargetProperty.h"
+#include "aidl/android/hardware/graphics/composer3/Color.h"
+#include "aidl/android/hardware/graphics/composer3/Composition.h"
+#include "aidl/android/hardware/graphics/composer3/ContentType.h"
+#include "aidl/android/hardware/graphics/composer3/DisplayAttribute.h"
+#include "aidl/android/hardware/graphics/composer3/DisplayCapability.h"
+#include "aidl/android/hardware/graphics/composer3/DisplayConnectionType.h"
+#include "aidl/android/hardware/graphics/composer3/FloatColor.h"
+#include "aidl/android/hardware/graphics/composer3/FormatColorComponent.h"
+#include "aidl/android/hardware/graphics/composer3/IComposer.h"
+#include "aidl/android/hardware/graphics/composer3/PerFrameMetadata.h"
+#include "aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h"
+#include "aidl/android/hardware/graphics/composer3/PerFrameMetadataKey.h"
+#include "aidl/android/hardware/graphics/composer3/PowerMode.h"
+#include "aidl/android/hardware/graphics/composer3/VsyncPeriodChangeConstraints.h"
+#include "aidl/android/hardware/graphics/composer3/VsyncPeriodChangeTimeline.h"
+#include "android/hardware/graphics/composer/2.1/IComposer.h"
+#include "android/hardware/graphics/composer/2.1/IComposerCallback.h"
+#include "android/hardware/graphics/composer/2.1/IComposerClient.h"
+#include "android/hardware/graphics/composer/2.2/IComposerClient.h"
+#include "android/hardware/graphics/composer/2.3/IComposerClient.h"
+#include "android/hardware/graphics/composer/2.4/IComposerClient.h"
+#include "android/hardware/graphics/composer/2.4/types.h"
+
+namespace android::h2a {
+
+static_assert(
+        aidl::android::hardware::graphics::composer3::IComposer::EX_NO_RESOURCES ==
+        static_cast<int32_t>(::android::hardware::graphics::composer::V2_4::Error::NO_RESOURCES));
+
+static_assert(
+        aidl::android::hardware::graphics::composer3::IComposerClient::EX_BAD_CONFIG ==
+        static_cast<int32_t>(::android::hardware::graphics::composer::V2_4::Error::BAD_CONFIG));
+static_assert(
+        aidl::android::hardware::graphics::composer3::IComposerClient::EX_BAD_DISPLAY ==
+        static_cast<int32_t>(::android::hardware::graphics::composer::V2_4::Error::BAD_DISPLAY));
+static_assert(
+        aidl::android::hardware::graphics::composer3::IComposerClient::EX_BAD_LAYER ==
+        static_cast<int32_t>(::android::hardware::graphics::composer::V2_4::Error::BAD_LAYER));
+static_assert(
+        aidl::android::hardware::graphics::composer3::IComposerClient::EX_BAD_PARAMETER ==
+        static_cast<int32_t>(::android::hardware::graphics::composer::V2_4::Error::BAD_PARAMETER));
+static_assert(
+        aidl::android::hardware::graphics::composer3::IComposerClient::EX_NO_RESOURCES ==
+        static_cast<int32_t>(::android::hardware::graphics::composer::V2_4::Error::NO_RESOURCES));
+static_assert(
+        aidl::android::hardware::graphics::composer3::IComposerClient::EX_NOT_VALIDATED ==
+        static_cast<int32_t>(::android::hardware::graphics::composer::V2_4::Error::NOT_VALIDATED));
+static_assert(
+        aidl::android::hardware::graphics::composer3::IComposerClient::EX_UNSUPPORTED ==
+        static_cast<int32_t>(::android::hardware::graphics::composer::V2_4::Error::UNSUPPORTED));
+static_assert(
+        aidl::android::hardware::graphics::composer3::IComposerClient::EX_SEAMLESS_NOT_ALLOWED ==
+        static_cast<int32_t>(
+                ::android::hardware::graphics::composer::V2_4::Error::SEAMLESS_NOT_ALLOWED));
+static_assert(
+        aidl::android::hardware::graphics::composer3::IComposerClient::EX_SEAMLESS_NOT_POSSIBLE ==
+        static_cast<int32_t>(
+                ::android::hardware::graphics::composer::V2_4::Error::SEAMLESS_NOT_POSSIBLE));
+
+static_assert(
+        aidl::android::hardware::graphics::composer3::Capability::INVALID ==
+        static_cast<aidl::android::hardware::graphics::composer3::Capability>(
+                ::android::hardware::graphics::composer::V2_1::IComposer::Capability::INVALID));
+static_assert(aidl::android::hardware::graphics::composer3::Capability::SIDEBAND_STREAM ==
+              static_cast<aidl::android::hardware::graphics::composer3::Capability>(
+                      ::android::hardware::graphics::composer::V2_1::IComposer::Capability::
+                              SIDEBAND_STREAM));
+static_assert(
+        aidl::android::hardware::graphics::composer3::Capability::SKIP_CLIENT_COLOR_TRANSFORM ==
+        static_cast<aidl::android::hardware::graphics::composer3::Capability>(
+                ::android::hardware::graphics::composer::V2_1::IComposer::Capability::
+                        SKIP_CLIENT_COLOR_TRANSFORM));
+static_assert(
+        aidl::android::hardware::graphics::composer3::Capability::PRESENT_FENCE_IS_NOT_RELIABLE ==
+        static_cast<aidl::android::hardware::graphics::composer3::Capability>(
+                ::android::hardware::graphics::composer::V2_1::IComposer::Capability::
+                        PRESENT_FENCE_IS_NOT_RELIABLE));
+// HWC2_CAPABILITY_SKIP_VALIDATE was never defined for HIDL, so we just hardcode its value
+static_assert(aidl::android::hardware::graphics::composer3::Capability::SKIP_VALIDATE ==
+              static_cast<aidl::android::hardware::graphics::composer3::Capability>(4));
+
+static_assert(aidl::android::hardware::graphics::composer3::DisplayRequest::LayerRequest::
+                      CLEAR_CLIENT_TARGET ==
+              static_cast<int>(::android::hardware::graphics::composer::V2_1::IComposerClient::
+                                       LayerRequest::CLEAR_CLIENT_TARGET));
+
+static_assert(aidl::android::hardware::graphics::common::BlendMode::INVALID ==
+              static_cast<aidl::android::hardware::graphics::common::BlendMode>(
+                      ::android::hardware::graphics::composer::V2_1::IComposerClient::BlendMode::
+                              INVALID));
+static_assert(
+        aidl::android::hardware::graphics::common::BlendMode::NONE ==
+        static_cast<aidl::android::hardware::graphics::common::BlendMode>(
+                ::android::hardware::graphics::composer::V2_1::IComposerClient::BlendMode::NONE));
+static_assert(aidl::android::hardware::graphics::common::BlendMode::PREMULTIPLIED ==
+              static_cast<aidl::android::hardware::graphics::common::BlendMode>(
+                      ::android::hardware::graphics::composer::V2_1::IComposerClient::BlendMode::
+                              PREMULTIPLIED));
+static_assert(aidl::android::hardware::graphics::common::BlendMode::COVERAGE ==
+              static_cast<aidl::android::hardware::graphics::common::BlendMode>(
+                      ::android::hardware::graphics::composer::V2_1::IComposerClient::BlendMode::
+                              COVERAGE));
+
+static_assert(aidl::android::hardware::graphics::composer3::Composition::INVALID ==
+              static_cast<aidl::android::hardware::graphics::composer3::Composition>(
+                      ::android::hardware::graphics::composer::V2_1::IComposerClient::Composition::
+                              INVALID));
+static_assert(aidl::android::hardware::graphics::composer3::Composition::CLIENT ==
+              static_cast<aidl::android::hardware::graphics::composer3::Composition>(
+                      ::android::hardware::graphics::composer::V2_1::IComposerClient::Composition::
+                              CLIENT));
+static_assert(aidl::android::hardware::graphics::composer3::Composition::DEVICE ==
+              static_cast<aidl::android::hardware::graphics::composer3::Composition>(
+                      ::android::hardware::graphics::composer::V2_1::IComposerClient::Composition::
+                              DEVICE));
+static_assert(aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR ==
+              static_cast<aidl::android::hardware::graphics::composer3::Composition>(
+                      ::android::hardware::graphics::composer::V2_1::IComposerClient::Composition::
+                              SOLID_COLOR));
+static_assert(aidl::android::hardware::graphics::composer3::Composition::CURSOR ==
+              static_cast<aidl::android::hardware::graphics::composer3::Composition>(
+                      ::android::hardware::graphics::composer::V2_1::IComposerClient::Composition::
+                              CURSOR));
+static_assert(aidl::android::hardware::graphics::composer3::Composition::SIDEBAND ==
+              static_cast<aidl::android::hardware::graphics::composer3::Composition>(
+                      ::android::hardware::graphics::composer::V2_1::IComposerClient::Composition::
+                              SIDEBAND));
+
+static_assert(aidl::android::hardware::graphics::composer3::DisplayRequest::FLIP_CLIENT_TARGET ==
+              static_cast<int>(::android::hardware::graphics::composer::V2_1::IComposerClient::
+                                       DisplayRequest::FLIP_CLIENT_TARGET));
+static_assert(aidl::android::hardware::graphics::composer3::DisplayRequest::
+                      WRITE_CLIENT_TARGET_TO_OUTPUT ==
+              static_cast<int>(::android::hardware::graphics::composer::V2_1::IComposerClient::
+                                       DisplayRequest::WRITE_CLIENT_TARGET_TO_OUTPUT));
+
+static_assert(
+        aidl::android::hardware::graphics::composer3::PowerMode::OFF ==
+        static_cast<aidl::android::hardware::graphics::composer3::PowerMode>(
+                ::android::hardware::graphics::composer::V2_2::IComposerClient::PowerMode::OFF));
+static_assert(
+        aidl::android::hardware::graphics::composer3::PowerMode::DOZE ==
+        static_cast<aidl::android::hardware::graphics::composer3::PowerMode>(
+                ::android::hardware::graphics::composer::V2_2::IComposerClient::PowerMode::DOZE));
+static_assert(aidl::android::hardware::graphics::composer3::PowerMode::DOZE_SUSPEND ==
+              static_cast<aidl::android::hardware::graphics::composer3::PowerMode>(
+                      ::android::hardware::graphics::composer::V2_2::IComposerClient::PowerMode::
+                              DOZE_SUSPEND));
+static_assert(
+        aidl::android::hardware::graphics::composer3::PowerMode::ON ==
+        static_cast<aidl::android::hardware::graphics::composer3::PowerMode>(
+                ::android::hardware::graphics::composer::V2_2::IComposerClient::PowerMode::ON));
+static_assert(aidl::android::hardware::graphics::composer3::PowerMode::ON_SUSPEND ==
+              static_cast<aidl::android::hardware::graphics::composer3::PowerMode>(
+                      ::android::hardware::graphics::composer::V2_2::IComposerClient::PowerMode::
+                              ON_SUSPEND));
+
+static_assert(aidl::android::hardware::graphics::composer3::DisplayCapability::INVALID ==
+              static_cast<aidl::android::hardware::graphics::composer3::DisplayCapability>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::
+                              DisplayCapability::INVALID));
+static_assert(aidl::android::hardware::graphics::composer3::DisplayCapability::
+                      SKIP_CLIENT_COLOR_TRANSFORM ==
+              static_cast<aidl::android::hardware::graphics::composer3::DisplayCapability>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::
+                              DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM));
+static_assert(aidl::android::hardware::graphics::composer3::DisplayCapability::DOZE ==
+              static_cast<aidl::android::hardware::graphics::composer3::DisplayCapability>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::
+                              DisplayCapability::DOZE));
+static_assert(aidl::android::hardware::graphics::composer3::DisplayCapability::BRIGHTNESS ==
+              static_cast<aidl::android::hardware::graphics::composer3::DisplayCapability>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::
+                              DisplayCapability::BRIGHTNESS));
+static_assert(aidl::android::hardware::graphics::composer3::DisplayCapability::PROTECTED_CONTENTS ==
+              static_cast<aidl::android::hardware::graphics::composer3::DisplayCapability>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::
+                              DisplayCapability::PROTECTED_CONTENTS));
+static_assert(
+        aidl::android::hardware::graphics::composer3::DisplayCapability::AUTO_LOW_LATENCY_MODE ==
+        static_cast<aidl::android::hardware::graphics::composer3::DisplayCapability>(
+                ::android::hardware::graphics::composer::V2_4::IComposerClient::DisplayCapability::
+                        AUTO_LOW_LATENCY_MODE));
+
+static_assert(aidl::android::hardware::graphics::composer3::DisplayAttribute::INVALID ==
+              static_cast<aidl::android::hardware::graphics::composer3::DisplayAttribute>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::Attribute::
+                              INVALID));
+static_assert(
+        aidl::android::hardware::graphics::composer3::DisplayAttribute::WIDTH ==
+        static_cast<aidl::android::hardware::graphics::composer3::DisplayAttribute>(
+                ::android::hardware::graphics::composer::V2_4::IComposerClient::Attribute::WIDTH));
+static_assert(
+        aidl::android::hardware::graphics::composer3::DisplayAttribute::HEIGHT ==
+        static_cast<aidl::android::hardware::graphics::composer3::DisplayAttribute>(
+                ::android::hardware::graphics::composer::V2_4::IComposerClient::Attribute::HEIGHT));
+static_assert(aidl::android::hardware::graphics::composer3::DisplayAttribute::VSYNC_PERIOD ==
+              static_cast<aidl::android::hardware::graphics::composer3::DisplayAttribute>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::Attribute::
+                              VSYNC_PERIOD));
+static_assert(
+        aidl::android::hardware::graphics::composer3::DisplayAttribute::DPI_X ==
+        static_cast<aidl::android::hardware::graphics::composer3::DisplayAttribute>(
+                ::android::hardware::graphics::composer::V2_4::IComposerClient::Attribute::DPI_X));
+static_assert(
+        aidl::android::hardware::graphics::composer3::DisplayAttribute::DPI_Y ==
+        static_cast<aidl::android::hardware::graphics::composer3::DisplayAttribute>(
+                ::android::hardware::graphics::composer::V2_4::IComposerClient::Attribute::DPI_Y));
+static_assert(aidl::android::hardware::graphics::composer3::DisplayAttribute::CONFIG_GROUP ==
+              static_cast<aidl::android::hardware::graphics::composer3::DisplayAttribute>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::Attribute::
+                              CONFIG_GROUP));
+
+static_assert(aidl::android::hardware::graphics::composer3::DisplayConnectionType::INTERNAL ==
+              static_cast<aidl::android::hardware::graphics::composer3::DisplayConnectionType>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::
+                              DisplayConnectionType::INTERNAL));
+static_assert(aidl::android::hardware::graphics::composer3::DisplayConnectionType::EXTERNAL ==
+              static_cast<aidl::android::hardware::graphics::composer3::DisplayConnectionType>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::
+                              DisplayConnectionType::EXTERNAL));
+
+static_assert(
+        aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X ==
+        static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                        PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X));
+static_assert(
+        aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y ==
+        static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                        PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y));
+static_assert(aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::
+                      DISPLAY_GREEN_PRIMARY_X ==
+              static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                      ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                              PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X));
+static_assert(aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::
+                      DISPLAY_GREEN_PRIMARY_Y ==
+              static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                      ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                              PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y));
+static_assert(
+        aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X ==
+        static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                        PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X));
+static_assert(
+        aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y ==
+        static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                        PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y));
+static_assert(aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::WHITE_POINT_X ==
+              static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                      ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                              PerFrameMetadataKey::WHITE_POINT_X));
+static_assert(aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::WHITE_POINT_Y ==
+              static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                      ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                              PerFrameMetadataKey::WHITE_POINT_Y));
+static_assert(aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::MAX_LUMINANCE ==
+              static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                      ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                              PerFrameMetadataKey::MAX_LUMINANCE));
+static_assert(aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::MIN_LUMINANCE ==
+              static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                      ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                              PerFrameMetadataKey::MIN_LUMINANCE));
+static_assert(aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::
+                      MAX_CONTENT_LIGHT_LEVEL ==
+              static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                      ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                              PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL));
+static_assert(aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::
+                      MAX_FRAME_AVERAGE_LIGHT_LEVEL ==
+              static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                      ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                              PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL));
+static_assert(aidl::android::hardware::graphics::composer3::PerFrameMetadataKey::HDR10_PLUS_SEI ==
+              static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(
+                      ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                              PerFrameMetadataKey::HDR10_PLUS_SEI));
+
+static_assert(
+        aidl::android::hardware::graphics::composer3::FormatColorComponent::FORMAT_COMPONENT_0 ==
+        static_cast<aidl::android::hardware::graphics::composer3::FormatColorComponent>(
+                ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                        FormatColorComponent::FORMAT_COMPONENT_0));
+static_assert(
+        aidl::android::hardware::graphics::composer3::FormatColorComponent::FORMAT_COMPONENT_1 ==
+        static_cast<aidl::android::hardware::graphics::composer3::FormatColorComponent>(
+                ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                        FormatColorComponent::FORMAT_COMPONENT_1));
+static_assert(
+        aidl::android::hardware::graphics::composer3::FormatColorComponent::FORMAT_COMPONENT_2 ==
+        static_cast<aidl::android::hardware::graphics::composer3::FormatColorComponent>(
+                ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                        FormatColorComponent::FORMAT_COMPONENT_2));
+static_assert(
+        aidl::android::hardware::graphics::composer3::FormatColorComponent::FORMAT_COMPONENT_3 ==
+        static_cast<aidl::android::hardware::graphics::composer3::FormatColorComponent>(
+                ::android::hardware::graphics::composer::V2_3::IComposerClient::
+                        FormatColorComponent::FORMAT_COMPONENT_3));
+
+static_assert(
+        aidl::android::hardware::graphics::composer3::ContentType::NONE ==
+        static_cast<aidl::android::hardware::graphics::composer3::ContentType>(
+                ::android::hardware::graphics::composer::V2_4::IComposerClient::ContentType::NONE));
+static_assert(aidl::android::hardware::graphics::composer3::ContentType::GRAPHICS ==
+              static_cast<aidl::android::hardware::graphics::composer3::ContentType>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::ContentType::
+                              GRAPHICS));
+static_assert(aidl::android::hardware::graphics::composer3::ContentType::PHOTO ==
+              static_cast<aidl::android::hardware::graphics::composer3::ContentType>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::ContentType::
+                              PHOTO));
+static_assert(aidl::android::hardware::graphics::composer3::ContentType::CINEMA ==
+              static_cast<aidl::android::hardware::graphics::composer3::ContentType>(
+                      ::android::hardware::graphics::composer::V2_4::IComposerClient::ContentType::
+                              CINEMA));
+static_assert(
+        aidl::android::hardware::graphics::composer3::ContentType::GAME ==
+        static_cast<aidl::android::hardware::graphics::composer3::ContentType>(
+                ::android::hardware::graphics::composer::V2_4::IComposerClient::ContentType::GAME));
+
+static_assert(
+        aidl::android::hardware::graphics::composer3::PresentOrValidate::Result::Presented ==
+        static_cast<aidl::android::hardware::graphics::composer3::PresentOrValidate::Result>(1));
+static_assert(
+        aidl::android::hardware::graphics::composer3::PresentOrValidate::Result::Validated ==
+        static_cast<aidl::android::hardware::graphics::composer3::PresentOrValidate::Result>(0));
+
+}  // namespace android::h2a
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposer.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposer.aidl
new file mode 100644
index 0000000..b8edd80
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposer.aidl
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.Capability;
+import android.hardware.graphics.composer3.IComposerClient;
+
+@VintfStability
+interface IComposer {
+    /**
+     * Temporary failure due to resource contention Exception
+     */
+    const int EX_NO_RESOURCES = 6;
+
+    /**
+     * Creates a client of the composer.
+     *
+     * @return is the newly created client.
+     *
+     * @exception EX_NO_RESOURCES when the client could not be created.
+     */
+    IComposerClient createClient();
+
+    /**
+     * Retrieves implementation-defined debug information, which will be
+     * displayed during, for example, `dumpsys SurfaceFlinger`.
+     *
+     * @return is a string of debug information.
+     */
+    String dumpDebugInfo();
+
+    /**
+     * Provides a list of supported capabilities (as described in the
+     * definition of Capability above). This list must not change after
+     * initialization.
+     *
+     * @return is a list of supported capabilities.
+     */
+    Capability[] getCapabilities();
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl
new file mode 100644
index 0000000..ac95b41
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.VsyncPeriodChangeTimeline;
+
+@VintfStability
+interface IComposerCallback {
+    /**
+     * Notifies the client that the given display has either been connected or
+     * disconnected. Every active display (even a built-in physical display)
+     * must trigger at least one hotplug notification, even if it only occurs
+     * immediately after callback registration.
+     *
+     * Displays which have been connected are assumed to be in PowerMode.OFF,
+     * and the onVsync callback should not be called for a display until vsync
+     * has been enabled with setVsyncEnabled.
+     *
+     * The client may call back into the device while the callback is in
+     * progress. The device must serialize calls to this callback such that
+     * only one thread is calling it at a time.
+     *
+     * @param display is the display that triggers the hotplug event.
+     * @param connected indicates whether the display is connected or
+     *        disconnected.
+     */
+    void onHotplug(long display, boolean connected);
+
+    /**
+     * Notifies the client to trigger a screen refresh. This forces all layer
+     * state for this display to be resent, and the display to be validated
+     * and presented, even if there have been no changes.
+     *
+     * This refresh will occur some time after the callback is initiated, but
+     * not necessarily before it returns.  It is safe to trigger this callback
+     * from other functions which call into the device.
+     *
+     * @param display is the display to refresh.
+     */
+    oneway void onRefresh(long display);
+
+    /**
+     * Notifies the client that the conditions which previously led to returning
+     * SEAMLESS_NOT_POSSIBLE from setActiveConfigWithConstraints have changed and now seamless may
+     * be possible. Client should retry calling setActiveConfigWithConstraints.
+     *
+     * @param display is a display setActiveConfigWithConstraints previously failed with
+     * EX_SEAMLESS_NOT_POSSIBLE.
+     */
+    oneway void onSeamlessPossible(long display);
+
+    /**
+     * Notifies the client that a vsync event has occurred. This callback must
+     * only be triggered when vsync is enabled for this display (through
+     * setVsyncEnabled).
+     *
+     * @param display is the display which has received a vsync event
+     * @param timestamp is the CLOCK_MONOTONIC time at which the vsync event
+     *        occurred, in nanoseconds.
+     * @param vsyncPeriodNanos is the display vsync period in nanoseconds i.e. the next onVsync
+     *        is expected to be called vsyncPeriodNanos nanoseconds after this call.
+     */
+    oneway void onVsync(long display, long timestamp, int vsyncPeriodNanos);
+
+    /**
+     * Notifies the client that the previously reported timing for vsync period change has been
+     * updated. This may occur if the composer missed the deadline for changing the vsync period
+     * or the client submitted a refresh frame too late.
+     *
+     * @param display is the display which vsync period change is in progress
+     * @param updatedTimeline is the new timeline for the vsync period change.
+     */
+    oneway void onVsyncPeriodTimingChanged(
+            long display, in VsyncPeriodChangeTimeline updatedTimeline);
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
new file mode 100644
index 0000000..ab7f397
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -0,0 +1,731 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.ClientTargetProperty;
+import android.hardware.graphics.composer3.ColorMode;
+import android.hardware.graphics.composer3.CommandResultPayload;
+import android.hardware.graphics.composer3.ContentType;
+import android.hardware.graphics.composer3.DisplayAttribute;
+import android.hardware.graphics.composer3.DisplayCapability;
+import android.hardware.graphics.composer3.DisplayCommand;
+import android.hardware.graphics.composer3.DisplayConnectionType;
+import android.hardware.graphics.composer3.DisplayContentSample;
+import android.hardware.graphics.composer3.DisplayContentSamplingAttributes;
+import android.hardware.graphics.composer3.DisplayIdentification;
+import android.hardware.graphics.composer3.FormatColorComponent;
+import android.hardware.graphics.composer3.HdrCapabilities;
+import android.hardware.graphics.composer3.IComposerCallback;
+import android.hardware.graphics.composer3.PerFrameMetadataKey;
+import android.hardware.graphics.composer3.PowerMode;
+import android.hardware.graphics.composer3.ReadbackBufferAttributes;
+import android.hardware.graphics.composer3.RenderIntent;
+import android.hardware.graphics.composer3.VirtualDisplay;
+import android.hardware.graphics.composer3.VsyncPeriodChangeConstraints;
+import android.hardware.graphics.composer3.VsyncPeriodChangeTimeline;
+
+@VintfStability
+interface IComposerClient {
+    /**
+     * Invalid Config Exception
+     */
+    const int EX_BAD_CONFIG = 1;
+
+    /**
+     * Invalid Display Exception
+     */
+    const int EX_BAD_DISPLAY = 2;
+
+    /**
+     * Invalid Layer Exception
+     */
+    const int EX_BAD_LAYER = 3;
+
+    /**
+     * Invalid width, height, etc.
+     */
+    const int EX_BAD_PARAMETER = 4;
+
+    /**
+     * Reserved for historical reasons
+     */
+    const int EX_RESERVED = 5;
+    /**
+     * Temporary failure due to resource contention Exception
+     */
+    const int EX_NO_RESOURCES = 6;
+
+    /**
+     * validateDisplay has not been called Exception
+     */
+    const int EX_NOT_VALIDATED = 7;
+
+    /**
+     * Seamless cannot be required for configurations that don't share a
+     * config group Exception
+     */
+    const int EX_UNSUPPORTED = 8;
+
+    const int EX_SEAMLESS_NOT_ALLOWED = 9;
+    /**
+     * Seamless requirements cannot be met Exception
+     */
+    const int EX_SEAMLESS_NOT_POSSIBLE = 10;
+
+    /**
+     * Integer.MAX_VALUE is reserved for the invalid configuration.
+     * This should not be returned as a valid configuration.
+     */
+    const int INVALID_CONFIGURATION = 0x7fffffff;
+
+    /**
+     * Creates a new layer on the given display.
+     *
+     * @param display is the display on which to create the layer.
+     * @param bufferSlotCount is the number of buffer slot to be reserved.
+     *
+     * @return is the handle of the new layer.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_NO_RESOURCES when the device was unable to create a layer this
+     *                      time.
+     */
+    long createLayer(long display, int bufferSlotCount);
+
+    /**
+     * Creates a new virtual display with the given width and height. The
+     * format passed into this function is the default format requested by the
+     * consumer of the virtual display output buffers.
+     *
+     * The display must be assumed to be on from the time the first frame is
+     * presented until the display is destroyed.
+     *
+     * @param width is the width in pixels.
+     * @param height is the height in pixels.
+     * @param formatHint is the default output buffer format selected by
+     *        the consumer.
+     * @param outputBufferSlotCount is the number of output buffer slots to be
+     *        reserved.
+     *
+     * @return is the newly-created virtual display.
+     *
+     * @exception EX_UNSUPPORTED when the width or height is too large for the
+     *                     device to be able to create a virtual display.
+     * @exception EX_NO_RESOURCES when the device is unable to create a new virtual
+     *                      display at this time.
+     */
+    VirtualDisplay createVirtualDisplay(int width, int height,
+            android.hardware.graphics.common.PixelFormat formatHint, int outputBufferSlotCount);
+
+    /**
+     * Destroys the given layer.
+     *
+     * @param display is the display on which the layer was created.
+     * @param layer is the layer to destroy.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_LAYER when an invalid layer handle was passed in.
+     */
+    void destroyLayer(long display, long layer);
+
+    /**
+     * Destroys a virtual display. After this call all resources consumed by
+     * this display may be freed by the device and any operations performed on
+     * this display must fail.
+     *
+     * @param display is the virtual display to destroy.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_PARAMETER when the display handle which was passed in does
+     *                       not refer to a virtual display.
+     */
+    void destroyVirtualDisplay(long display);
+
+    /**
+     * Executes commands.
+     *
+     * @param commands are the commands to be processed.
+     *
+     * @return are the command statuses.
+     */
+    CommandResultPayload[] executeCommands(in DisplayCommand[] commands);
+
+    /**
+     * Retrieves which display configuration is currently active.
+     *
+     * If no display configuration is currently active, this function raise
+     * the exception EX_BAD_CONFIG. It is the responsibility of the client to call
+     * setActiveConfig with a valid configuration before attempting to present
+     * anything on the display.
+     *
+     * @param display is the display to which the active config is queried.
+     *
+     * @return is the currently active display configuration.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_CONFIG when no configuration is currently active.
+     */
+    int getActiveConfig(long display);
+
+    /**
+     * Returns the color modes supported on this display.
+     *
+     * All devices must support at least ColorMode.NATIVE.
+     *
+     * @param display is the display to query.
+     *
+     * @return is an array of color modes.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     */
+    ColorMode[] getColorModes(long display);
+
+    /**
+     * By default, layer dataspaces are mapped to the current color mode
+     * colorimetrically with a few exceptions.
+     *
+     * When the layer dataspace is a legacy dataspace (see
+     * common@1.1::Dataspace) and the display render intent is
+     * RenderIntent.ENHANCE, the pixel values can go through an
+     * implementation-defined saturation transform before being mapped to the
+     * current color mode colorimetrically.
+     *
+     * Colors that are out of the gamut of the current color mode are
+     * hard-clipped.
+     *
+     *
+     * Returns the saturation matrix of the specified legacy dataspace.
+     *
+     * The saturation matrix can be used to approximate the legacy dataspace
+     * saturation transform. It is to be applied on linear pixel values like
+     * this:
+     *
+     *   (in GLSL)
+     *   linearSrgb = saturationMatrix * linearSrgb;
+     *
+     * @param dataspace must be Dataspace::SRGB_LINEAR.
+     *
+     * @return is the 4x4 column-major matrix used to approximate the
+     *         legacy dataspace saturation operation. The last row must be
+     *         [0.0, 0.0, 0.0, 1.0].
+     *
+     * @exception EX_BAD_PARAMETER when an invalid dataspace was passed in.
+     */
+    float[] getDataspaceSaturationMatrix(android.hardware.graphics.common.Dataspace dataspace);
+
+    /**
+     * Returns a display attribute value for a particular display
+     * configuration.
+     *
+     * @param display is the display to query.
+     * @param config is the display configuration for which to return
+     *        attribute values.
+     *
+     * @return is the value of the attribute.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_CONFIG when config does not name a valid configuration for
+     *                    this display.
+     * @exception EX_BAD_PARAMETER when attribute is unrecognized.
+     * @exception EX_UNSUPPORTED when attribute cannot be queried for the config.
+     */
+    int getDisplayAttribute(long display, int config, DisplayAttribute attribute);
+
+    /**
+     * Provides a list of supported capabilities (as described in the
+     * definition of DisplayCapability above). This list must not change after
+     * initialization.
+     *
+     * @return is a list of supported capabilities.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     */
+    DisplayCapability[] getDisplayCapabilities(long display);
+
+    /**
+     * Returns handles for all of the valid display configurations on this
+     * display.
+     * This should never return INVALID_CONFIGURATION as a valid value.
+     *
+     * @param display is the display to query.
+     *
+     * @return is an array of configuration handles.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     */
+    int[] getDisplayConfigs(long display);
+
+    /**
+     * Returns whether the given physical display is internal or external.
+     *
+     * @return is the connection type of the display.
+     *
+     * @exception EX_BAD_DISPLAY when the given display is invalid or virtual.
+     */
+    DisplayConnectionType getDisplayConnectionType(long display);
+
+    /**
+     * Returns the port and data that describe a physical display. The port is
+     * a unique number that identifies a physical connector (e.g. eDP, HDMI)
+     * for display output. The data blob is parsed to determine its format,
+     * typically EDID 1.3 as specified in VESA E-EDID Standard Release A
+     * Revision 1.
+     *
+     * @param display is the display to query.
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_UNSUPPORTED when identification data is unavailable.
+     * @return the connector to which the display is connected and the EDID 1.3
+     *         blob identifying the display.
+     */
+    DisplayIdentification getDisplayIdentificationData(long display);
+
+    /**
+     * Returns a human-readable version of the display's name.
+     *
+     * @return is the name of the display.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     */
+    String getDisplayName(long display);
+
+    /**
+     * Retrieves which vsync period the display is currently using.
+     *
+     * If no display configuration is currently active, this function must
+     * return BAD_CONFIG. If the vsync period is about to change due to a
+     * setActiveConfigWithConstraints call, this function must return the current vsync period
+     * until the change takes place.
+     *
+     * @param display is the display for which the vsync period is queried.
+     *
+     * @return is the current vsync period of the display.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_CONFIG when no configuration is currently active.
+     */
+    int getDisplayVsyncPeriod(long display);
+
+    /**
+     * Collects the results of display content color sampling for display.
+     *
+     * Collection of data can occur whether the sampling is in ENABLE or
+     * DISABLE state.
+     *
+     * @param  display     is the display to which the sampling is collected.
+     * @param  maxFrames   is the maximum number of frames that should be represented in the sample.
+     *                     The sample represents the most-recently posted frames.
+     *                     If maxFrames is 0, all frames are to be represented by the sample.
+     * @param  timestamp   is the timestamp after which any frames were posted that should be
+     *                     included in the sample. Timestamp is CLOCK_MONOTONIC.
+     *                     If timestamp is 0, do not filter from the sample by time.
+     *
+     * @return is the sample.
+     *
+     * @exception EX_BAD_DISPLAY   when an invalid display was passed in, or
+     * @exception EX_UNSUPPORTED   when there is no efficient way to sample, or
+     * @exception EX_BAD_PARAMETER when the component is not supported by the hardware.
+     */
+    DisplayContentSample getDisplayedContentSample(long display, long maxFrames, long timestamp);
+
+    /**
+     * Query for what types of color sampling the hardware supports.
+     *
+     * @param  display        is the display where the samples are collected.
+     *
+     * @return are the sampling attributes
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display was passed in, or
+     * @exception EX_UNSUPPORTED when there is no efficient way to sample.
+     */
+    DisplayContentSamplingAttributes getDisplayedContentSamplingAttributes(long display);
+
+    /**
+     * Returns the high dynamic range (HDR) capabilities of the given display,
+     * which are invariant with regard to the active configuration.
+     *
+     * Displays which are not HDR-capable must return no types.
+     *
+     * @param display is the display to query.
+     *
+     * @return are the HDR capabilities
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     */
+    HdrCapabilities getHdrCapabilities(long display);
+
+    /**
+     * Returns the maximum number of virtual displays supported by this device
+     * (which may be 0). The client must not attempt to create more than this
+     * many virtual displays on this device. This number must not change for
+     * the lifetime of the device.
+     *
+     * @return is the maximum number of virtual displays supported.
+     */
+    int getMaxVirtualDisplayCount();
+
+    /**
+     * Returns the PerFrameMetadataKeys that are supported by this device.
+     *
+     * @param display is the display on which to create the layer.
+     * @return is the vector of PerFrameMetadataKey keys that are
+     *        supported by this device.
+     * @exception EX_UNSUPPORTED if not supported on underlying HAL
+     */
+    PerFrameMetadataKey[] getPerFrameMetadataKeys(long display);
+
+    /**
+     * Returns the format which should be used when allocating a buffer for use by
+     * device readback as well as the dataspace in which its contents must be
+     * interpreted.
+     *
+     * The width and height of this buffer must be those of the currently-active
+     * display configuration, and the usage flags must consist of the following:
+     *   BufferUsage.CPU_READ | BufferUsage.GPU_TEXTURE |
+     *   BufferUsage.COMPOSER_OUTPUT
+     *
+     * The format and dataspace provided must be sufficient such that if a
+     * correctly-configured buffer is passed into setReadbackBuffer, filled by
+     * the device, and then displayed by the client as a full-screen buffer, the
+     * output of the display remains the same (subject to the note about protected
+     * content in the description of setReadbackBuffer).
+     *
+     * If the active configuration or color mode of this display has changed
+     * since a previous call to this function, it must be called again prior to
+     * setting a readback buffer such that the returned format and dataspace will
+     * be updated accordingly.
+     *
+     * Parameters:
+     * @param display - the display on which to create the layer.
+     *
+     * @return is the readback buffer attributes.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_UNSUPPORTED if not supported on underlying HAL
+     *
+     * See also:
+     *   setReadbackBuffer
+     *   getReadbackBufferFence
+     */
+    ReadbackBufferAttributes getReadbackBufferAttributes(long display);
+
+    /**
+     * Returns an acquire sync fence file descriptor which must signal when the
+     * buffer provided to setReadbackBuffer has been filled by the device and is
+     * safe for the client to read.
+     *
+     * If it is already safe to read from this buffer, -1 may be returned instead.
+     * The client takes ownership of this file descriptor and is responsible for
+     * closing it when it is no longer needed.
+     *
+     * This function must be called immediately after the composition cycle being
+     * captured into the readback buffer. The complete ordering of a readback buffer
+     * capture is as follows:
+     *
+     *   getReadbackBufferAttributes
+     *   // Readback buffer is allocated
+     *   // Many frames may pass
+     *
+     *   setReadbackBuffer
+     *   validateDisplay
+     *   presentDisplay
+     *   getReadbackBufferFence
+     *   // Implicitly wait on the acquire fence before accessing the buffer
+     *
+     * Parameters:
+     * @param display - the display on which to create the layer.
+     *
+     * @return is a sync fence file descriptor as described above; pointer
+     *       must be non-NULL
+     *
+     * @exception EX_BAD_DISPLAY - an invalid display handle was passed in
+     * @exception EX_NO_RESOURCES - the readback operation was successful, but
+     *                        resulted in a different validate result than would
+     *                        have occurred without readback
+     * @exception EX_UNSUPPORTED - the readback operation was unsuccessful because of
+     *                       resource constraints, the presence of protected
+     *                       content, or other reasons; -1 must be returned for
+     *                       acquireFence
+     *
+     * See also:
+     *   getReadbackBufferAttributes
+     *   setReadbackBuffer
+     */
+    @nullable ParcelFileDescriptor getReadbackBufferFence(long display);
+
+    /**
+     * Returns the render intents supported by the specified display and color
+     * mode.
+     *
+     * For SDR color modes, RenderIntent.COLORIMETRIC must be supported. For
+     * HDR color modes, RenderIntent.TONE_MAP_COLORIMETRIC must be supported.
+     *
+     * @param display is the display to query.
+     * @param mode is the color mode to query.
+     *
+     * @return is an array of render intents.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_PARAMETER when an invalid color mode was passed in.
+     */
+    RenderIntent[] getRenderIntents(long display, ColorMode mode);
+
+    /**
+     * Provides a list of all the content types supported by this display (any of
+     * ContentType.{GRAPHICS, PHOTO, CINEMA, GAME}). This list must not change after
+     * initialization.
+     *
+     * Content types are introduced in HDMI 1.4 and supporting them is optional. The
+     * ContentType.NONE is always supported and will not be returned by this method..
+     *
+     * @return out is a list of supported content types.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     */
+    ContentType[] getSupportedContentTypes(long display);
+
+    /**
+     * Provides a IComposerCallback object for the device to call.
+     *
+     * This function must be called only once.
+     *
+     * @param callback is the IComposerCallback object.
+     */
+    void registerCallback(in IComposerCallback callback);
+
+    /**
+     * Sets the active configuration for this display. Upon returning, the
+     * given display configuration must be active and remain so until either
+     * this function is called again or the display is disconnected.
+     *
+     * @param display is the display to which the active config is set.
+     * @param config is the new display configuration.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_CONFIG when the configuration handle passed in is not valid
+     *                    for this display.
+     */
+    void setActiveConfig(long display, int config);
+
+    /**
+     * Sets the active configuration and the refresh rate for this display.
+     * If the new config shares the same config group as the current config,
+     * only the vsync period shall change.
+     * Upon returning, the given display configuration, except vsync period, must be active and
+     * remain so until either this function is called again or the display is disconnected.
+     * When the display starts to refresh at the new vsync period, onVsync_2_4 callback must be
+     * called with the new vsync period.
+     *
+     * @param display is the display for which the active config is set.
+     * @param config is the new display configuration.
+     * @param vsyncPeriodChangeConstraints are the constraints required for changing vsync period.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_CONFIG when the configuration handle passed in is not valid
+     *                    for this display.
+     * @exception EX_SEAMLESS_NOT_ALLOWED when seamlessRequired was true but config provided doesn't
+     *                              share the same config group as the current config.
+     * @exception EX_SEAMLESS_NOT_POSSIBLE when seamlessRequired was true but the display cannot
+     * achieve the vsync period change without a noticeable visual artifact. When the conditions
+     * change and it may be possible to change the vsync period seamlessly, onSeamlessPossible
+     * callback must be called to indicate that caller should retry.
+     *
+     * @return is the timeline for the vsync period change.
+     */
+    VsyncPeriodChangeTimeline setActiveConfigWithConstraints(
+            long display, int config, in VsyncPeriodChangeConstraints vsyncPeriodChangeConstraints);
+
+    /**
+     * 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
+     * the display is internally connected and a custom low latency mode is available, that should
+     * be triggered.
+     *
+     * This function should only be called if the display reports support for
+     * DisplayCapability.AUTO_LOW_LATENCY_MODE from getDisplayCapabilities_2_4.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_UNSUPPORTED when AUTO_LOW_LATENCY_MODE is not supported by the composer
+     *                           implementation or the given display
+     */
+    void setAutoLowLatencyMode(long display, boolean on);
+
+    /**
+     * Set the number of client target slots to be reserved.
+     *
+     * @param display is the display to which the slots are reserved.
+     * @param clientTargetSlotCount is the slot count for client targets.
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_NO_RESOURCES when unable to reserve the slots.
+     */
+    void setClientTargetSlotCount(long display, int clientTargetSlotCount);
+
+    /**
+     * Sets the color mode and render intent of the given display.
+     *
+     * The color mode and render intent change must take effect on next
+     * presentDisplay.
+     *
+     * All devices must support at least ColorMode.NATIVE and
+     * RenderIntent.COLORIMETRIC, and displays are assumed to be in this mode
+     * upon hotplug.
+     *
+     * @param display is the display to which the color mode is set.
+     * @param mode is the color mode to set to.
+     * @param intent is the render intent to set to.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_PARAMETER when mode or intent is invalid
+     * @exception EX_UNSUPPORTED when mode or intent is not supported on this
+     *         display.
+     */
+    void setColorMode(long display, ColorMode mode, RenderIntent intent);
+
+    /**
+     * Instructs the connected display that the content being shown is of the given type - one of
+     * GRAPHICS, PHOTO, CINEMA, GAME.
+     *
+     * Content types are introduced in HDMI 1.4 and supporting them is optional. If they are
+     * supported, this signal should switch the display to a mode that is optimal for the given
+     * type of content. See HDMI 1.4 specification for more information.
+     *
+     * If the display is internally connected (not through HDMI), and such modes are available,
+     * this method should trigger them.
+     *
+     * This function can be called for a content type even if no support for it is
+     * reported from getSupportedContentTypes.
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_UNSUPPORTED when the given content type is not supported by the composer
+     *         implementation or the given display
+     */
+    void setContentType(long display, ContentType type);
+
+    /**
+     * Sets the brightness of a display.
+     *
+     * Ideally, the brightness change should take effect in the next frame post (so that it can be
+     * aligned with color transforms).
+     *
+     * @param display
+     *      The display whose brightness is set.
+     * @param brightness
+     *      A number between 0.0f (minimum brightness) and 1.0f (maximum brightness), or -1.0 to
+     *      turn the backlight off.
+     *
+     * @exception EX_BAD_DISPLAY   when the display is invalid, or
+     * @exception EX_UNSUPPORTED   when brightness operations are not supported, or
+     * @exception EX_BAD_PARAMETER when the brightness is invalid, or
+     * @exception EX_NO_RESOURCES  when the brightness cannot be applied.
+     */
+    void setDisplayBrightness(long display, float brightness);
+
+    /**
+     * Enables or disables the collection of color content statistics
+     * on this display.
+     *
+     * Sampling occurs on the contents of the final composition on this display
+     * (i.e., the contents presented on screen). Samples should be collected after all
+     * color transforms have been applied.
+     *
+     * Sampling support is optional, and is set to DISABLE by default.
+     * On each call to ENABLE, all collected statistics must be reset.
+     *
+     * Sample data can be queried via getDisplayedContentSample().
+     *
+     * @param display        is the display to which the sampling mode is set.
+     * @param enabled        indicates whether to enable or disable sampling.
+     * @param componentMask  The mask of which components should be sampled. If zero, all supported
+     *                       components are to be enabled.
+     * @param maxFrames      is the maximum number of frames that should be stored before discard.
+     *                       The sample represents the most-recently posted frames.
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in,
+     * @exception EX_BAD_PARAMETER when enabled was an invalid value, or
+     * @exception EX_NO_RESOURCES when the requested ringbuffer size via maxFrames was
+     *                                 not available.
+     * @exception EX_UNSUPPORTED when there is no efficient way to sample.
+     */
+    void setDisplayedContentSamplingEnabled(
+            long display, boolean enable, FormatColorComponent componentMask, long maxFrames);
+
+    /**
+     * Sets the power mode of the given display. The transition must be
+     * complete when this function returns. It is valid to call this function
+     * multiple times with the same power mode.
+     *
+     * All displays must support PowerMode.ON and PowerMode.OFF.  Whether a
+     * display supports PowerMode.DOZE or PowerMode.DOZE_SUSPEND may be
+     * queried using getDozeSupport.
+     *
+     * @param display is the display to which the power mode is set.
+     * @param mode is the new power mode.
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_PARAMETER when mode was not a valid power mode.
+     * @exception EX_UNSUPPORTED when mode is not supported on this display.
+     */
+    void setPowerMode(long display, PowerMode mode);
+
+    /**
+     * Sets the readback buffer to be filled with the contents of the next
+     * composition performed for this display (i.e., the contents present at the
+     * time of the next validateDisplay/presentDisplay cycle).
+     *
+     * This buffer must have been allocated as described in
+     * getReadbackBufferAttributes and is in the dataspace provided by the same.
+     *
+     * Also provides a file descriptor referring to a release sync fence
+     * object, which must be signaled when it is safe to write to the readback
+     * buffer. If it is already safe to write to the readback buffer, null may be passed instead.
+     *
+     * If there is hardware protected content on the display at the time of the next
+     * composition, the area of the readback buffer covered by such content must be
+     * completely black. Any areas of the buffer not covered by such content may
+     * optionally be black as well.
+     *
+     *
+     * This function must not be called between any call to validateDisplay and a
+     * subsequent call to presentDisplay.
+     *
+     * Parameters:
+     * @param display - the display on which to create the layer.
+     * @param buffer - the new readback buffer
+     * @param releaseFence - a sync fence file descriptor as described above or null if it is
+     *                       already safe to write to the readback buffer.
+     *
+     * @exception EX_BAD_DISPLAY - an invalid display handle was passed in
+     * @exception EX_BAD_PARAMETER - the new readback buffer handle was invalid
+     *
+     * See also:
+     *   getReadbackBufferAttributes
+     *   getReadbackBufferFence
+     */
+    void setReadbackBuffer(long display, in android.hardware.common.NativeHandle buffer,
+            in @nullable ParcelFileDescriptor releaseFence);
+
+    /**
+     * Enables or disables the vsync signal for the given display. Virtual
+     * displays never generate vsync callbacks, and any attempt to enable
+     * vsync for a virtual display though this function must succeed and have
+     * no other effect.
+     *
+     * @param display is the display to which the vsync mode is set.
+     * @param enabled indicates whether to enable or disable vsync
+     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @exception EX_BAD_PARAMETER when enabled was an invalid value.
+     */
+    void setVsyncEnabled(long display, boolean enabled);
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
new file mode 100644
index 0000000..44fd4dc
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
@@ -0,0 +1,267 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.common.NativeHandle;
+import android.hardware.graphics.common.FRect;
+import android.hardware.graphics.common.Point;
+import android.hardware.graphics.common.Rect;
+import android.hardware.graphics.composer3.Buffer;
+import android.hardware.graphics.composer3.Color;
+import android.hardware.graphics.composer3.FloatColor;
+import android.hardware.graphics.composer3.ParcelableBlendMode;
+import android.hardware.graphics.composer3.ParcelableComposition;
+import android.hardware.graphics.composer3.ParcelableDataspace;
+import android.hardware.graphics.composer3.ParcelableTransform;
+import android.hardware.graphics.composer3.PerFrameMetadata;
+import android.hardware.graphics.composer3.PerFrameMetadataBlob;
+import android.hardware.graphics.composer3.PlaneAlpha;
+import android.hardware.graphics.composer3.WhitePointNits;
+import android.hardware.graphics.composer3.ZOrder;
+
+@VintfStability
+parcelable LayerCommand {
+    /**
+     * The layer which this commands refers to.
+     * @see IComposer.createLayer
+     */
+    long layer;
+
+    /**
+     * Asynchronously sets the position of a cursor layer.
+     *
+     * Prior to validateDisplay, a layer may be marked as Composition.CURSOR.
+     * If validation succeeds (i.e., the device does not request a composition
+     * change for that layer), then once a buffer has been set for the layer
+     * and it has been presented, its position may be set by this function at
+     * any time between presentDisplay and any subsequent validateDisplay
+     * calls for this display.
+     *
+     * Once validateDisplay is called, this function must not be called again
+     * until the validate/present sequence is completed.
+     *
+     * May be called from any thread so long as it is not interleaved with the
+     * validate/present sequence as described above.
+     */
+    @nullable Point cursorPosition;
+
+    /**
+     * Sets the buffer handle to be displayed for this layer. If the buffer
+     * properties set at allocation time (width, height, format, and usage)
+     * have not changed since the previous frame, it is not necessary to call
+     * validateDisplay before calling presentDisplay unless new state needs to
+     * be validated in the interim.
+     *
+     * Also provides a file descriptor referring to an acquire sync fence
+     * object, which must be signaled when it is safe to read from the given
+     * buffer. If it is already safe to read from the buffer, an empty handle
+     * may be passed instead.
+     *
+     * This function must return NONE and have no other effect if called for a
+     * layer with a composition type of Composition.SOLID_COLOR (because it
+     * has no buffer) or Composition.SIDEBAND or Composition.CLIENT (because
+     * synchronization and buffer updates for these layers are handled
+     * elsewhere).
+     */
+    @nullable Buffer buffer;
+
+    /**
+     * Provides the region of the source buffer which has been modified since
+     * the last frame. This region does not need to be validated before
+     * calling presentDisplay.
+     *
+     * Once set through this function, the damage region remains the same
+     * until a subsequent call to this function.
+     *
+     * If damage is non-empty, then it may be assumed that any portion of the
+     * source buffer not covered by one of the rects has not been modified
+     * this frame. If damage is empty, then the whole source buffer must be
+     * treated as if it has been modified.
+     *
+     * If the layer's contents are not modified relative to the prior frame,
+     * damage must contain exactly one empty rect([0, 0, 0, 0]).
+     *
+     * The damage rects are relative to the pre-transformed buffer, and their
+     * origin is the top-left corner. They must not exceed the dimensions of
+     * the latched buffer.
+     */
+    @nullable Rect[] damage;
+
+    /**
+     * Sets the blend mode of the given layer.
+     */
+    @nullable ParcelableBlendMode blendMode;
+
+    /**
+     * Sets the color of the given layer. If the composition type of the layer
+     * is not Composition.SOLID_COLOR, this call must succeed and have no
+     * other effect.
+     */
+    @nullable Color color;
+
+    /**
+     * Sets the color of the given layer. If the composition type of the layer
+     * is not Composition.SOLID_COLOR, this call must succeed and have no
+     * other effect.
+     */
+    @nullable FloatColor floatColor;
+
+    /**
+     * Sets the desired composition type of the given layer. During
+     * validateDisplay, the device may request changes to the composition
+     * types of any of the layers as described in the definition of
+     * Composition above.
+     */
+    @nullable ParcelableComposition composition;
+
+    /**
+     * Sets the dataspace of the layer.
+     *
+     * The dataspace provides more information about how to interpret the buffer
+     * or solid color, such as the encoding standard and color transform.
+     *
+     * See the values of ParcelableDataspace for more information.
+     */
+    @nullable ParcelableDataspace dataspace;
+
+    /**
+     * Sets the display frame (the portion of the display covered by a layer)
+     * of the given layer. This frame must not exceed the display dimensions.
+     */
+    @nullable Rect displayFrame;
+
+    /**
+     * Sets an alpha value (a floating point value in the range [0.0, 1.0])
+     * which will be applied to the whole layer. It can be conceptualized as a
+     * preprocessing step which applies the following function:
+     *   if (blendMode == BlendMode.PREMULTIPLIED)
+     *       out.rgb = in.rgb * planeAlpha
+     *   out.a = in.a * planeAlpha
+     *
+     * If the device does not support this operation on a layer which is
+     * marked Composition.DEVICE, it must request a composition type change
+     * to Composition.CLIENT upon the next validateDisplay call.
+     *
+     */
+    @nullable PlaneAlpha planeAlpha;
+
+    /**
+     * Sets the sideband stream for this layer. If the composition type of the
+     * given layer is not Composition.SIDEBAND, this call must succeed and
+     * have no other effect.
+     */
+    @nullable NativeHandle sidebandStream;
+
+    /**
+     * Sets the source crop (the portion of the source buffer which will fill
+     * the display frame) of the given layer. This crop rectangle must not
+     * exceed the dimensions of the latched buffer.
+     *
+     * If the device is not capable of supporting a true float source crop
+     * (i.e., it will truncate or round the floats to integers), it must set
+     * this layer to Composition.CLIENT when crop is non-integral for the
+     * most accurate rendering.
+     *
+     * If the device cannot support float source crops, but still wants to
+     * handle the layer, it must use the following code (or similar) to
+     * convert to an integer crop:
+     *   intCrop.left = (int) ceilf(crop.left);
+     *   intCrop.top = (int) ceilf(crop.top);
+     *   intCrop.right = (int) floorf(crop.right);
+     *   intCrop.bottom = (int) floorf(crop.bottom);
+     */
+    @nullable FRect sourceCrop;
+
+    /**
+     * Sets the transform (rotation/flip) of the given layer.
+     */
+    @nullable ParcelableTransform transform;
+
+    /**
+     * Specifies the portion of the layer that is visible, including portions
+     * under translucent areas of other layers. The region is in screen space,
+     * and must not exceed the dimensions of the screen.
+     */
+    @nullable Rect[] visibleRegion;
+
+    /**
+     * Sets the desired Z order (height) of the given layer. A layer with a
+     * greater Z value occludes a layer with a lesser Z value.
+     */
+    @nullable ZOrder z;
+
+    /**
+     * Sets a matrix for color transform which will be applied on this layer
+     * before composition.
+     *
+     * If the device is not capable of apply the matrix on this layer, it must force
+     * this layer to client composition during VALIDATE_DISPLAY.
+     *
+     * The matrix provided is an affine color transformation of the following
+     * form:
+     *
+     * |r.r r.g r.b 0|
+     * |g.r g.g g.b 0|
+     * |b.r b.g b.b 0|
+     * |Tr  Tg  Tb  1|
+     *
+     * This matrix must be provided in row-major form:
+     *
+     * {r.r, r.g, r.b, 0, g.r, ...}.
+     *
+     * Given a matrix of this form and an input color [R_in, G_in, B_in],
+     * the input color must first be converted to linear space
+     * [R_linear, G_linear, B_linear], then the output linear color
+     * [R_out_linear, G_out_linear, B_out_linear] will be:
+     *
+     * R_out_linear = R_linear * r.r + G_linear * g.r + B_linear * b.r + Tr
+     * G_out_linear = R_linear * r.g + G_linear * g.g + B_linear * b.g + Tg
+     * B_out_linear = R_linear * r.b + G_linear * g.b + B_linear * b.b + Tb
+     *
+     * [R_out_linear, G_out_linear, B_out_linear] must then be converted to
+     * gamma space: [R_out, G_out, B_out] before blending.
+     */
+    @nullable float[] colorTransform;
+
+    /**
+     * Sets the desired white point for the layer. This is intended to be used when presenting
+     * an SDR layer alongside HDR content. The HDR content will be presented at the display
+     * brightness in nits, and accordingly SDR content shall be dimmed to the desired white point
+     * provided.
+     */
+    @nullable WhitePointNits whitePointNits;
+
+    /**
+     * Sets the PerFrameMetadata for the display. This metadata must be used
+     * by the implementation to better tone map content to that display.
+     *
+     * This is a command that may be called every frame.
+     */
+    @nullable PerFrameMetadata[] perFrameMetadata;
+
+    /**
+     * This command sends metadata that may be used for tone-mapping the
+     * associated layer.  The metadata structure follows a {key, blob}
+     * format (see the PerFrameMetadataBlob struct).  All keys must be
+     * returned by a prior call to getPerFrameMetadataKeys and must
+     * be part of the list of keys associated with blob-type metadata
+     * (see PerFrameMetadataKey).
+     *
+     * This command may be called every frame.
+     */
+    @nullable PerFrameMetadataBlob[] perFrameMetadataBlob;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableBlendMode.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableBlendMode.aidl
new file mode 100644
index 0000000..a6c016a
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableBlendMode.aidl
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.common.BlendMode;
+
+@VintfStability
+parcelable ParcelableBlendMode {
+    BlendMode blendMode;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableComposition.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableComposition.aidl
new file mode 100644
index 0000000..0946ce7
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableComposition.aidl
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.Composition;
+
+@VintfStability
+parcelable ParcelableComposition {
+    Composition composition;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableDataspace.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableDataspace.aidl
new file mode 100644
index 0000000..528cdf9
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableDataspace.aidl
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.common.Dataspace;
+
+@VintfStability
+parcelable ParcelableDataspace {
+    Dataspace dataspace;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableTransform.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableTransform.aidl
new file mode 100644
index 0000000..75f9f7e
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableTransform.aidl
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.common.Transform;
+
+@VintfStability
+parcelable ParcelableTransform {
+    Transform transform;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/PerFrameMetadata.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PerFrameMetadata.aidl
new file mode 100644
index 0000000..a6588a4
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PerFrameMetadata.aidl
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.PerFrameMetadataKey;
+
+/**
+ * PerFrameMetadata
+ * This struct encapsulates float-valued
+ * metadata - key must not be in the list
+ * of keys representing blob-formatted metadata
+ * (see PerFrameMetadataKey)
+ */
+@VintfStability
+parcelable PerFrameMetadata {
+    PerFrameMetadataKey key;
+    float value;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.aidl
new file mode 100644
index 0000000..a82773c
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.aidl
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.PerFrameMetadataKey;
+
+/**
+ * PerFrameMetadataBlob
+ * This struct encapsulates blob
+ * metadata - key must be one of the list of keys
+ * associated with blob-type metadata key
+ * and the blob must adhere to the format specified by
+ * that key (See PerFrameMetadataKey).
+ */
+@VintfStability
+parcelable PerFrameMetadataBlob {
+    PerFrameMetadataKey key;
+    byte[] blob;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/PerFrameMetadataKey.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PerFrameMetadataKey.aidl
new file mode 100644
index 0000000..3962920
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PerFrameMetadataKey.aidl
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+/**
+ * PerFrameMetadataKey
+ *
+ * A set of PerFrameMetadataKey pertains specifically to blob-formatted
+ * metadata (as opposed to float-valued metadata).
+ * The list of keys that represent blobs are:
+ * 1. HDR10_PLUS_SEI
+ */
+@VintfStability
+@Backing(type="int")
+enum PerFrameMetadataKey {
+    /**
+     * SMPTE ST 2084:2014.
+     * Coordinates defined in CIE 1931 xy chromaticity space
+     *
+     *
+     * SMPTE ST 2084:2014
+     */
+    DISPLAY_RED_PRIMARY_X,
+    /**
+     * SMPTE ST 2084:2014
+     */
+    DISPLAY_RED_PRIMARY_Y,
+    /**
+     * SMPTE ST 2084:2014
+     */
+    DISPLAY_GREEN_PRIMARY_X,
+    /**
+     * SMPTE ST 2084:2014
+     */
+    DISPLAY_GREEN_PRIMARY_Y,
+    /**
+     * SMPTE ST 2084:2014
+     */
+    DISPLAY_BLUE_PRIMARY_X,
+    /**
+     * SMPTE ST 2084:2014
+     */
+    DISPLAY_BLUE_PRIMARY_Y,
+    /**
+     * SMPTE ST 2084:2014
+     */
+    WHITE_POINT_X,
+    /**
+     * SMPTE ST 2084:2014
+     */
+    WHITE_POINT_Y,
+    /**
+     * SMPTE ST 2084:2014.
+     * Units: nits
+     * max as defined by ST 2048: 10,000 nits
+     */
+    MAX_LUMINANCE,
+    /**
+     * SMPTE ST 2084:2014
+     */
+    MIN_LUMINANCE,
+    /**
+     * CTA 861.3
+     */
+    MAX_CONTENT_LIGHT_LEVEL,
+    /**
+     * CTA 861.3
+     */
+    MAX_FRAME_AVERAGE_LIGHT_LEVEL,
+    /**
+     * HDR10+ metadata
+     * Specifies a metadata blob adhering to
+     * the ST2094-40 SEI message spec, Version 1.0
+     */
+    HDR10_PLUS_SEI,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/PlaneAlpha.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PlaneAlpha.aidl
new file mode 100644
index 0000000..347dc19
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PlaneAlpha.aidl
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable PlaneAlpha {
+    /**
+     * An alpha value (a floating point value in the range [0.0, 1.0])
+     * which will be applied to a whole layer.
+     * @see LayerCommand.planeAlpha
+     */
+    float alpha;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/PowerMode.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PowerMode.aidl
new file mode 100644
index 0000000..2c56933
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PowerMode.aidl
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.PowerMode;
+
+@VintfStability
+@Backing(type="int")
+enum PowerMode {
+    /**
+     * The display is fully off (blanked).
+     */
+    OFF = 0,
+    /**
+     * These are optional low power modes. getDozeSupport may be called to
+     * determine whether a given display supports these modes.
+     *
+     *
+     * The display is turned on and configured in a low power state that
+     * is suitable for presenting ambient information to the user,
+     * possibly with lower fidelity than ON, but with greater efficiency.
+     */
+    DOZE = 1,
+    /**
+     * The display is configured as in DOZE but may stop applying display
+     * updates from the client. This is effectively a hint to the device
+     * that drawing to the display has been suspended and that the
+     * device must remain on in a low power state and continue
+     * displaying its current contents indefinitely until the power mode
+     * changes.
+     *
+     * This mode may also be used as a signal to enable hardware-based
+     * doze functionality. In this case, the device is free to take over
+     * the display and manage it autonomously to implement a low power
+     * always-on display.
+     */
+    DOZE_SUSPEND = 3,
+    /**
+     * The display is fully on.
+     */
+    ON = 2,
+    /**
+     * The display is configured as in ON but may stop applying display
+     * updates from the client. This is effectively a hint to the device
+     * that drawing to the display has been suspended and that the
+     * device must remain on and continue displaying its current contents
+     * indefinitely until the power mode changes.
+     *
+     * This mode may also be used as a signal to enable hardware-based
+     * functionality to take over the display and manage it autonomously
+     * to implement a low power always-on display.
+     */
+    ON_SUSPEND = 4,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/PresentFence.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentFence.aidl
new file mode 100644
index 0000000..244b4e5
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentFence.aidl
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable PresentFence {
+    /**
+     * The display which this commands refers to.
+     * @see IComposer.createDisplay
+     */
+    long display;
+
+    /**
+     * The present fence for this display.
+     */
+    ParcelFileDescriptor fence;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/PresentOrValidate.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentOrValidate.aidl
new file mode 100644
index 0000000..5ae8940
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentOrValidate.aidl
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable PresentOrValidate {
+    /**
+     * The display which this commands refers to.
+     * @see IComposer.createDisplay
+     */
+    long display;
+
+    /**
+     * Whether PresentOrValidate presented or validated the display.
+     */
+    @VintfStability enum Result { Validated, Presented }
+    Result result;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ReadbackBufferAttributes.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ReadbackBufferAttributes.aidl
new file mode 100644
index 0000000..8241ddd
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ReadbackBufferAttributes.aidl
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable ReadbackBufferAttributes {
+    android.hardware.graphics.common.PixelFormat format;
+    android.hardware.graphics.common.Dataspace dataspace;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ReleaseFences.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ReleaseFences.aidl
new file mode 100644
index 0000000..459a042
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ReleaseFences.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable ReleaseFences {
+    /**
+     * The display which this commands refers to.
+     * @see IComposer.createDisplay
+     */
+    long display;
+    @VintfStability
+    parcelable Layer {
+        /**
+         * The layer which this commands refers to.
+         * @see IComposer.createLayer
+         */
+        long layer;
+
+        /**
+         * The release fence for this layer.
+         */
+        ParcelFileDescriptor fence;
+    }
+
+    /**
+     * The layers which has release fences.
+     */
+    Layer[] layers;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/RenderIntent.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/RenderIntent.aidl
new file mode 100644
index 0000000..debf32c
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/RenderIntent.aidl
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+/**
+ * RenderIntent defines the mapping from color mode colors to display colors.
+ *
+ * A render intent must not change how it maps colors when the color mode
+ * changes. That is to say that when a render intent maps color C to color C',
+ * the fact that color C can have different pixel values in different color
+ * modes should not affect the mapping.
+ *
+ * RenderIntent overrides the render intents defined for individual color
+ * modes. It is ignored when the color mode is ColorMode.NATIVE, because
+ * ColorMode.NATIVE colors are already display colors.
+ */
+@VintfStability
+@Backing(type="int")
+enum RenderIntent {
+    /**
+     * Colors in the display gamut are unchanged. Colors out of the display
+     * gamut are hard-clipped.
+     *
+     * This implies that the display must have been calibrated unless
+     * ColorMode.NATIVE is the only supported color mode.
+     */
+    COLORIMETRIC = 0,
+    /**
+     * Enhance colors that are in the display gamut. Colors out of the display
+     * gamut are hard-clipped.
+     *
+     * The enhancement typically picks the biggest standard color space (e.g.
+     * DCI-P3) that is narrower than the display gamut and stretches it to the
+     * display gamut. The stretching is recommended to preserve skin tones.
+     */
+    ENHANCE = 1,
+    /**
+     * Tone map high-dynamic-range colors to the display's dynamic range. The
+     * dynamic range of the colors are communicated separately. After tone
+     * mapping, the mapping to the display gamut is as defined in
+     * COLORIMETRIC.
+     */
+    TONE_MAP_COLORIMETRIC = 2,
+    /**
+     * Tone map high-dynamic-range colors to the display's dynamic range. The
+     * dynamic range of the colors are communicated separately. After tone
+     * mapping, the mapping to the display gamut is as defined in ENHANCE.
+     *
+     * The tone mapping step and the enhancing step must match
+     * TONE_MAP_COLORIMETRIC and ENHANCE respectively when they are also
+     * supported.
+     */
+    TONE_MAP_ENHANCE = 3,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/VirtualDisplay.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/VirtualDisplay.aidl
new file mode 100644
index 0000000..8bbdfe3
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/VirtualDisplay.aidl
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+/**
+ * The return value from IComposerClient.createVirtualDisplay
+ */
+@VintfStability
+parcelable VirtualDisplay {
+    /**
+     * The newly-created virtual display.
+     */
+    long display;
+    /**
+     * The format of the buffer the device will produce.
+     */
+    android.hardware.graphics.common.PixelFormat format;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/VsyncPeriodChangeConstraints.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/VsyncPeriodChangeConstraints.aidl
new file mode 100644
index 0000000..5ae6f3d
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/VsyncPeriodChangeConstraints.aidl
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+/**
+ * Constraints for changing vsync period.
+ */
+@VintfStability
+parcelable VsyncPeriodChangeConstraints {
+    /**
+     * Time in CLOCK_MONOTONIC after which the vsync period may change
+     * (i.e., the vsync period must not change before this time).
+     */
+    long desiredTimeNanos;
+    /**
+     * If true, requires that the vsync period change must happen seamlessly without
+     * a noticeable visual artifact.
+     */
+    boolean seamlessRequired;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/VsyncPeriodChangeTimeline.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/VsyncPeriodChangeTimeline.aidl
new file mode 100644
index 0000000..13fd051
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/VsyncPeriodChangeTimeline.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+/**
+ * Timing for a vsync period change.
+ */
+@VintfStability
+parcelable VsyncPeriodChangeTimeline {
+    /**
+     * The time in CLOCK_MONOTONIC when the new display will start to refresh at
+     * the new vsync period.
+     */
+    long newVsyncAppliedTimeNanos;
+    /**
+     * Set to true if the client is required to send a frame to be displayed before
+     * the change can take place.
+     */
+    boolean refreshRequired;
+    /**
+     * The time in CLOCK_MONOTONIC when the client is expected to send the new frame.
+     * Should be ignored if refreshRequired is false.
+     */
+    long refreshTimeNanos;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/WhitePointNits.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/WhitePointNits.aidl
new file mode 100644
index 0000000..2a1d1c6
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/WhitePointNits.aidl
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable WhitePointNits {
+    /**
+     * The desired white point for the layer. This is intended to be used when presenting
+     * an SDR layer alongside HDR content. The HDR content will be presented at the display
+     * brightness in nits, and accordingly SDR content shall be dimmed to the desired white point
+     * provided.
+     * @see LayerCommand.whitePointNits.
+     */
+    float nits;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ZOrder.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ZOrder.aidl
new file mode 100644
index 0000000..56cc200
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ZOrder.aidl
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable ZOrder {
+    /**
+     * The desired Z order (height) of the given layer. A layer with a
+     * greater Z value occludes a layer with a lesser Z value.
+     * @see LayerCommand.z;
+     */
+    int z;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/Android.bp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/Android.bp
new file mode 100644
index 0000000..741572d
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/Android.bp
@@ -0,0 +1,92 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    // 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: "VtsHalGraphicsComposer3_TargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+        // Needed for librenderengine
+        "skia_deps",
+    ],
+    srcs: [
+        "VtsHalGraphicsComposer3_TargetTest.cpp",
+        "VtsHalGraphicsComposer3_ReadbackTest.cpp",
+        "composer-vts/GraphicsComposerCallback.cpp",
+    ],
+
+    shared_libs: [
+        "libEGL",
+        "libGLESv1_CM",
+        "libGLESv2",
+        "libbinder_ndk",
+        "libbinder",
+        "libfmq",
+        "libbase",
+        "libsync",
+        "libui",
+        "libgui",
+        "libhidlbase",
+        "libprocessgroup",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
+        "android.hardware.graphics.allocator@4.0",
+        "libvndksupport",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer3-command-buffer",
+    ],
+    static_libs: [
+        "android.hardware.graphics.composer3-V1-ndk",
+        "android.hardware.graphics.common-V3-ndk",
+        "android.hardware.graphics.common@1.2",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
+        "android.hardware.graphics.allocator@4.0",
+        "android.hardware.graphics.composer@3-vts",
+        "android.hardware.graphics.mapper@2.0-vts",
+        "android.hardware.graphics.mapper@2.1-vts",
+        "android.hardware.graphics.mapper@3.0-vts",
+        "android.hardware.graphics.mapper@4.0-vts",
+        "libaidlcommonsupport",
+        "libgtest",
+        "librenderengine",
+        "libshaders",
+        "libtonemap",
+    ],
+    cflags: [
+        "-Wconversion",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/AndroidTest.xml b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..3f9971b
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<configuration description="Runs VtsHalGraphicsComposer3_TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalGraphicsComposer3_TargetTest->/data/local/tmp/VtsHalGraphicsComposer3_TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalGraphicsComposer3_TargetTest" />
+        <option name="native-test-timeout" value="900000"/>
+    </test>
+</configuration>
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/OWNERS b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/OWNERS
new file mode 100644
index 0000000..d95d98d
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 199413815
+
+# Graphics team
+adyabr@google.com
+alecmouri@google.com
+ramindani@google.com
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp
new file mode 100644
index 0000000..0ece1d5
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -0,0 +1,1262 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "graphics_composer_aidl_hal_readback_tests@3"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include <aidl/android/hardware/graphics/composer3/IComposer.h>
+#include <android/binder_manager.h>
+#include <composer-vts/include/ReadbackVts.h>
+#include <composer-vts/include/RenderEngineVts.h>
+#include <gtest/gtest.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
+#include "composer-vts/include/GraphicsComposerCallback.h"
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+namespace {
+
+using ::android::Rect;
+using common::Dataspace;
+using common::PixelFormat;
+
+class GraphicsCompositionTestBase : public ::testing::Test {
+  protected:
+    void SetUpBase(const std::string& name) {
+        ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
+        ASSERT_NE(binder, nullptr);
+        ASSERT_NO_FATAL_FAILURE(mComposer = IComposer::fromBinder(binder));
+        ASSERT_NE(mComposer, nullptr);
+        ASSERT_NO_FATAL_FAILURE(mComposer->createClient(&mComposerClient));
+        mComposerCallback = ::ndk::SharedRefBase::make<GraphicsComposerCallback>();
+        mComposerClient->registerCallback(mComposerCallback);
+
+        // assume the first display is primary and is never removed
+        mPrimaryDisplay = waitForFirstDisplay();
+
+        ASSERT_NO_FATAL_FAILURE(mInvalidDisplayId = GetInvalidDisplayId());
+
+        int32_t activeConfig;
+        EXPECT_TRUE(mComposerClient->getActiveConfig(mPrimaryDisplay, &activeConfig).isOk());
+        EXPECT_TRUE(mComposerClient
+                            ->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+                                                  DisplayAttribute::WIDTH, &mDisplayWidth)
+                            .isOk());
+        EXPECT_TRUE(mComposerClient
+                            ->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+                                                  DisplayAttribute::HEIGHT, &mDisplayHeight)
+                            .isOk());
+
+        setTestColorModes();
+
+        // explicitly disable vsync
+        EXPECT_TRUE(mComposerClient->setVsyncEnabled(mPrimaryDisplay, false).isOk());
+        mComposerCallback->setVsyncAllowed(false);
+
+        // set up gralloc
+        mGraphicBuffer = allocate();
+
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON));
+
+        ASSERT_NO_FATAL_FAILURE(
+                mTestRenderEngine = std::unique_ptr<TestRenderEngine>(new TestRenderEngine(
+                        ::android::renderengine::RenderEngineCreationArgs::Builder()
+                                .setPixelFormat(static_cast<int>(common::PixelFormat::RGBA_8888))
+                                .setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers)
+                                .setUseColorManagerment(true)
+                                .setEnableProtectedContext(false)
+                                .setPrecacheToneMapperShaderOnly(false)
+                                .setContextPriority(::android::renderengine::RenderEngine::
+                                                            ContextPriority::HIGH)
+                                .build())));
+
+        ::android::renderengine::DisplaySettings clientCompositionDisplay;
+        clientCompositionDisplay.physicalDisplay = Rect(mDisplayWidth, mDisplayHeight);
+        clientCompositionDisplay.clip = clientCompositionDisplay.physicalDisplay;
+
+        mTestRenderEngine->initGraphicBuffer(
+                static_cast<uint32_t>(mDisplayWidth), static_cast<uint32_t>(mDisplayHeight), 1,
+                static_cast<uint64_t>(
+                        static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+                        static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
+                        static_cast<uint64_t>(common::BufferUsage::GPU_RENDER_TARGET)));
+        mTestRenderEngine->setDisplaySettings(clientCompositionDisplay);
+    }
+
+    void TearDown() override {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF));
+        const auto errors = mReader.takeErrors();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty());
+
+        if (mComposerCallback != nullptr) {
+            EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+        }
+    }
+
+    ::android::sp<::android::GraphicBuffer> allocate() {
+        const auto width = static_cast<uint32_t>(mDisplayWidth);
+        const auto height = static_cast<uint32_t>(mDisplayHeight);
+        const auto usage = static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
+                           static_cast<uint32_t>(common::BufferUsage::CPU_READ_OFTEN);
+
+        return ::android::sp<::android::GraphicBuffer>::make(
+                width, height, ::android::PIXEL_FORMAT_RGBA_8888,
+                /*layerCount*/ 1u, usage, "VtsHalGraphicsComposer3_ReadbackTest");
+    }
+
+    void writeLayers(const std::vector<std::shared_ptr<TestLayer>>& layers) {
+        for (auto layer : layers) {
+            layer->write(mWriter);
+        }
+        execute();
+    }
+
+    void execute() {
+        const auto& commands = mWriter.getPendingCommands();
+        if (commands.empty()) {
+            mWriter.reset();
+            return;
+        }
+
+        std::vector<CommandResultPayload> results;
+        auto status = mComposerClient->executeCommands(commands, &results);
+        ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
+
+        mReader.parse(std::move(results));
+        mWriter.reset();
+    }
+
+    bool getHasReadbackBuffer() {
+        ReadbackBufferAttributes readBackBufferAttributes;
+        const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+                                                                        &readBackBufferAttributes);
+        mPixelFormat = readBackBufferAttributes.format;
+        mDataspace = readBackBufferAttributes.dataspace;
+        return error.isOk() && ReadbackHelper::readbackSupported(mPixelFormat, mDataspace);
+    }
+
+    std::shared_ptr<IComposer> mComposer;
+    std::shared_ptr<IComposerClient> mComposerClient;
+
+    std::shared_ptr<GraphicsComposerCallback> mComposerCallback;
+    // the first display and is assumed never to be removed
+    int64_t mPrimaryDisplay;
+    int64_t mInvalidDisplayId;
+    int32_t mDisplayWidth;
+    int32_t mDisplayHeight;
+    std::vector<ColorMode> mTestColorModes;
+    ComposerClientWriter mWriter;
+    ComposerClientReader mReader;
+    ::android::sp<::android::GraphicBuffer> mGraphicBuffer;
+    std::unique_ptr<TestRenderEngine> mTestRenderEngine;
+
+    common::PixelFormat mPixelFormat;
+    common::Dataspace mDataspace;
+
+    static constexpr uint32_t kClientTargetSlotCount = 64;
+
+  private:
+    int64_t waitForFirstDisplay() {
+        while (true) {
+            std::vector<int64_t> displays = mComposerCallback->getDisplays();
+            if (displays.empty()) {
+                usleep(5 * 1000);
+                continue;
+            }
+            return displays[0];
+        }
+    }
+
+    void setTestColorModes() {
+        mTestColorModes.clear();
+        std::vector<ColorMode> modes;
+        EXPECT_TRUE(mComposerClient->getColorModes(mPrimaryDisplay, &modes).isOk());
+
+        for (ColorMode mode : modes) {
+            if (std::find(ReadbackHelper::colorModes.begin(), ReadbackHelper::colorModes.end(),
+                          mode) != ReadbackHelper::colorModes.end()) {
+                mTestColorModes.push_back(mode);
+            }
+        }
+    }
+
+    // returns an invalid display id (one that has not been registered to a
+    // display.  Currently assuming that a device will never have close to
+    // std::numeric_limit<uint64_t>::max() displays registered while running tests
+    int64_t GetInvalidDisplayId() {
+        int64_t id = std::numeric_limits<int64_t>::max();
+        std::vector<int64_t> displays = mComposerCallback->getDisplays();
+        while (id > 0) {
+            if (std::none_of(displays.begin(), displays.end(),
+                             [&](const auto& display) { return id == display; })) {
+                return id;
+            }
+            id--;
+        }
+
+        // Although 0 could be an invalid display, a return value of 0
+        // from GetInvalidDisplayId means all other ids are in use, a condition which
+        // we are assuming a device will never have
+        EXPECT_NE(0, id);
+        return id;
+    }
+};
+
+class GraphicsCompositionTest : public GraphicsCompositionTestBase,
+                                public testing::WithParamInterface<std::string> {
+  public:
+    void SetUp() override { SetUpBase(GetParam()); }
+};
+
+TEST_P(GraphicsCompositionTest, SingleSolidColorLayer) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        common::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setColor(BLUE);
+        layer->setDisplayFrame(coloredSquare);
+        layer->setZOrder(10);
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        // expected color for each pixel
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        // if hwc cannot handle and asks for composition change,
+        // just succeed the test
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(layers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsCompositionTest, SetLayerBuffer) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2},
+                                       GREEN);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
+                                       BLUE);
+
+        auto layer = std::make_shared<TestBufferLayer>(
+                mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+                mDisplayHeight, common::PixelFormat::RGBA_8888);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+        layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+        ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        writeLayers(layers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(layers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsCompositionTest, SetLayerBufferNoEffect) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        common::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setColor(BLUE);
+        layer->setDisplayFrame(coloredSquare);
+        layer->setZOrder(10);
+        layer->write(mWriter);
+
+        // This following buffer call should have no effect
+        uint64_t usage =
+                static_cast<uint64_t>(static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+                                      static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN));
+
+        mGraphicBuffer->reallocate(static_cast<uint32_t>(mDisplayWidth),
+                                   static_cast<uint32_t>(mDisplayHeight), 1,
+                                   static_cast<uint32_t>(common::PixelFormat::RGBA_8888), usage);
+        mWriter.setLayerBuffer(mPrimaryDisplay, layer->getLayer(), 0, mGraphicBuffer->handle, -1);
+
+        // expected color for each pixel
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsCompositionTest, SetReadbackBuffer) {
+    if (!getHasReadbackBuffer()) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+}
+
+TEST_P(GraphicsCompositionTest, SetReadbackBufferBadDisplay) {
+    if (!getHasReadbackBuffer()) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    ASSERT_NE(nullptr, mGraphicBuffer);
+    ASSERT_EQ(::android::OK, mGraphicBuffer->initCheck());
+    aidl::android::hardware::common::NativeHandle bufferHandle =
+            ::android::dupToAidl(mGraphicBuffer->handle);
+    ::ndk::ScopedFileDescriptor fence = ::ndk::ScopedFileDescriptor(-1);
+
+    const auto error = mComposerClient->setReadbackBuffer(mInvalidDisplayId, bufferHandle, fence);
+
+    EXPECT_FALSE(error.isOk());
+    ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsCompositionTest, SetReadbackBufferBadParameter) {
+    if (!getHasReadbackBuffer()) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    aidl::android::hardware::common::NativeHandle bufferHandle =
+            ::android::dupToAidl(mGraphicBuffer->handle);
+    ndk::ScopedFileDescriptor releaseFence = ndk::ScopedFileDescriptor(-1);
+    const auto error =
+            mComposerClient->setReadbackBuffer(mPrimaryDisplay, bufferHandle, releaseFence);
+
+    EXPECT_FALSE(error.isOk());
+    ASSERT_EQ(IComposerClient::EX_BAD_PARAMETER, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsCompositionTest, GetReadbackBufferFenceInactive) {
+    if (!getHasReadbackBuffer()) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    ndk::ScopedFileDescriptor releaseFence;
+    const auto error = mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &releaseFence);
+
+    EXPECT_TRUE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsCompositionTest, ClientComposition) {
+    EXPECT_TRUE(mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount)
+                        .isOk());
+
+    for (ColorMode mode : mTestColorModes) {
+        EXPECT_TRUE(mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC)
+                            .isOk());
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2},
+                                       GREEN);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
+                                       BLUE);
+
+        auto layer = std::make_shared<TestBufferLayer>(
+                mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+                mDisplayHeight, PixelFormat::RGBA_FP16);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+        layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+        writeLayers(layers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+
+        auto changedCompositionTypes = mReader.takeChangedCompositionTypes(mPrimaryDisplay);
+        if (!changedCompositionTypes.empty()) {
+            ASSERT_EQ(1, changedCompositionTypes.size());
+            ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0].composition);
+
+            PixelFormat clientFormat = PixelFormat::RGBA_8888;
+            auto clientUsage = static_cast<uint32_t>(
+                    static_cast<uint32_t>(common::BufferUsage::CPU_READ_OFTEN) |
+                    static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
+                    static_cast<uint32_t>(common::BufferUsage::COMPOSER_CLIENT_TARGET));
+            Dataspace clientDataspace = ReadbackHelper::getDataspaceForColorMode(mode);
+            common::Rect damage{0, 0, mDisplayWidth, mDisplayHeight};
+
+            // create client target buffer
+            mGraphicBuffer->reallocate(layer->getWidth(), layer->getHeight(),
+                                       static_cast<int32_t>(common::PixelFormat::RGBA_8888),
+                                       layer->getLayerCount(), clientUsage);
+
+            ASSERT_NE(nullptr, mGraphicBuffer->handle);
+
+            void* clientBufData;
+            mGraphicBuffer->lock(clientUsage, layer->getAccessRegion(), &clientBufData);
+
+            ASSERT_NO_FATAL_FAILURE(
+                    ReadbackHelper::fillBuffer(layer->getWidth(), layer->getHeight(),
+                                               static_cast<uint32_t>(mGraphicBuffer->stride),
+                                               clientBufData, clientFormat, expectedColors));
+            EXPECT_EQ(::android::OK, mGraphicBuffer->unlock());
+
+            ndk::ScopedFileDescriptor fenceHandle;
+            EXPECT_TRUE(
+                    mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fenceHandle).isOk());
+
+            layer->setToClientComposition(mWriter);
+            mWriter.acceptDisplayChanges(mPrimaryDisplay);
+            mWriter.setClientTarget(mPrimaryDisplay, 0, mGraphicBuffer->handle, fenceHandle.get(),
+                                    clientDataspace, std::vector<common::Rect>(1, damage));
+            execute();
+            changedCompositionTypes = mReader.takeChangedCompositionTypes(mPrimaryDisplay);
+            ASSERT_TRUE(changedCompositionTypes.empty());
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) {
+    ASSERT_NO_FATAL_FAILURE(
+            mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount));
+
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight / 2}, GREEN);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, RED);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        auto deviceLayer = std::make_shared<TestBufferLayer>(
+                mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+                mDisplayHeight / 2, PixelFormat::RGBA_8888);
+        std::vector<Color> deviceColors(deviceLayer->getWidth() * deviceLayer->getHeight());
+        ReadbackHelper::fillColorsArea(deviceColors, static_cast<int32_t>(deviceLayer->getWidth()),
+                                       {0, 0, static_cast<int32_t>(deviceLayer->getWidth()),
+                                        static_cast<int32_t>(deviceLayer->getHeight())},
+                                       GREEN);
+        deviceLayer->setDisplayFrame({0, 0, static_cast<int32_t>(deviceLayer->getWidth()),
+                                      static_cast<int32_t>(deviceLayer->getHeight())});
+        deviceLayer->setZOrder(10);
+        deviceLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+        ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors));
+        deviceLayer->write(mWriter);
+
+        PixelFormat clientFormat = PixelFormat::RGBA_8888;
+        auto clientUsage = static_cast<uint32_t>(
+                static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+                static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
+                static_cast<uint32_t>(common::BufferUsage::COMPOSER_CLIENT_TARGET));
+        Dataspace clientDataspace = ReadbackHelper::getDataspaceForColorMode(mode);
+        int32_t clientWidth = mDisplayWidth;
+        int32_t clientHeight = mDisplayHeight / 2;
+
+        auto clientLayer = std::make_shared<TestBufferLayer>(
+                mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, clientWidth,
+                clientHeight, PixelFormat::RGBA_FP16, Composition::DEVICE);
+        common::Rect clientFrame = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight};
+        clientLayer->setDisplayFrame(clientFrame);
+        clientLayer->setZOrder(0);
+        clientLayer->write(mWriter);
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+
+        auto changedCompositionTypes = mReader.takeChangedCompositionTypes(mPrimaryDisplay);
+        if (changedCompositionTypes.size() != 1) {
+            continue;
+        }
+        // create client target buffer
+        ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0].composition);
+        mGraphicBuffer->reallocate(static_cast<uint32_t>(mDisplayWidth),
+                                   static_cast<uint32_t>(mDisplayHeight),
+                                   static_cast<int32_t>(common::PixelFormat::RGBA_8888),
+                                   clientLayer->getLayerCount(), clientUsage);
+        ASSERT_NE(nullptr, mGraphicBuffer->handle);
+
+        void* clientBufData;
+        mGraphicBuffer->lock(clientUsage, {0, 0, mDisplayWidth, mDisplayHeight}, &clientBufData);
+
+        std::vector<Color> clientColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(clientColors, mDisplayWidth, clientFrame, RED);
+        ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(
+                static_cast<uint32_t>(mDisplayWidth), static_cast<uint32_t>(mDisplayHeight),
+                mGraphicBuffer->getStride(), clientBufData, clientFormat, clientColors));
+        EXPECT_EQ(::android::OK, mGraphicBuffer->unlock());
+
+        ndk::ScopedFileDescriptor fenceHandle;
+        EXPECT_TRUE(mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fenceHandle).isOk());
+
+        clientLayer->setToClientComposition(mWriter);
+        mWriter.acceptDisplayChanges(mPrimaryDisplay);
+        mWriter.setClientTarget(mPrimaryDisplay, 0, mGraphicBuffer->handle, fenceHandle.get(),
+                                clientDataspace, std::vector<common::Rect>(1, clientFrame));
+        execute();
+        changedCompositionTypes = mReader.takeChangedCompositionTypes(mPrimaryDisplay);
+        ASSERT_TRUE(changedCompositionTypes.empty());
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsCompositionTest, SetLayerDamage) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        common::Rect redRect = {0, 0, mDisplayWidth / 4, mDisplayHeight / 4};
+
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+
+        auto layer = std::make_shared<TestBufferLayer>(
+                mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+                mDisplayHeight, PixelFormat::RGBA_8888);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+        layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+        ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+
+        // update surface damage and recheck
+        redRect = {mDisplayWidth / 4, mDisplayHeight / 4, mDisplayWidth / 2, mDisplayHeight / 2};
+        ReadbackHelper::clearColors(expectedColors, mDisplayWidth, mDisplayHeight, mDisplayWidth);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+
+        ASSERT_NO_FATAL_FAILURE(layer->fillBuffer(expectedColors));
+        layer->setSurfaceDamage(
+                std::vector<common::Rect>(1, {0, 0, mDisplayWidth / 2, mDisplayWidth / 2}));
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsCompositionTest, SetLayerPlaneAlpha) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        layer->setColor(RED);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+        layer->setAlpha(0);
+        layer->setBlendMode(BlendMode::PREMULTIPLIED);
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(layers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsCompositionTest, SetLayerSourceCrop) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
+                                       BLUE);
+
+        auto layer = std::make_shared<TestBufferLayer>(
+                mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+                mDisplayHeight, PixelFormat::RGBA_8888);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+        layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+        layer->setSourceCrop({0, static_cast<float>(mDisplayHeight / 2),
+                              static_cast<float>(mDisplayWidth),
+                              static_cast<float>(mDisplayHeight)});
+        ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+        // update expected colors to match crop
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight}, BLUE);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+        writeLayers(layers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(layers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsCompositionTest, SetLayerZOrder) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        common::Rect redRect = {0, 0, mDisplayWidth, mDisplayHeight / 2};
+        common::Rect blueRect = {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight};
+        auto redLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        redLayer->setColor(RED);
+        redLayer->setDisplayFrame(redRect);
+
+        auto blueLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        blueLayer->setColor(BLUE);
+        blueLayer->setDisplayFrame(blueRect);
+        blueLayer->setZOrder(5);
+
+        std::vector<std::shared_ptr<TestLayer>> layers = {redLayer, blueLayer};
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+
+        // red in front of blue
+        redLayer->setZOrder(10);
+
+        // fill blue first so that red will overwrite on overlap
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+
+        redLayer->setZOrder(1);
+        ReadbackHelper::clearColors(expectedColors, mDisplayWidth, mDisplayHeight, mDisplayWidth);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty());
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(layers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
+class GraphicsBlendModeCompositionTest
+    : public GraphicsCompositionTestBase,
+      public testing::WithParamInterface<std::tuple<std::string, std::string>> {
+  public:
+    void SetUp() override {
+        SetUpBase(std::get<0>(GetParam()));
+        mBackgroundColor = BLACK;
+        mTopLayerColor = RED;
+    }
+
+    void setBackgroundColor(Color color) { mBackgroundColor = color; }
+
+    void setTopLayerColor(Color color) { mTopLayerColor = color; }
+
+    void setUpLayers(BlendMode blendMode) {
+        mLayers.clear();
+        std::vector<Color> topLayerPixelColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(topLayerPixelColors, mDisplayWidth,
+                                       {0, 0, mDisplayWidth, mDisplayHeight}, mTopLayerColor);
+
+        auto backgroundLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        backgroundLayer->setZOrder(0);
+        backgroundLayer->setColor(mBackgroundColor);
+
+        auto layer = std::make_shared<TestBufferLayer>(
+                mComposerClient, mGraphicBuffer, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+                mDisplayHeight, PixelFormat::RGBA_8888);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+        layer->setDataspace(Dataspace::UNKNOWN, mWriter);
+        ASSERT_NO_FATAL_FAILURE(layer->setBuffer(topLayerPixelColors));
+
+        layer->setBlendMode(blendMode);
+        layer->setAlpha(std::stof(std::get<1>(GetParam())));
+
+        mLayers.push_back(backgroundLayer);
+        mLayers.push_back(layer);
+    }
+
+    void setExpectedColors(std::vector<Color>& expectedColors) {
+        ASSERT_EQ(2, mLayers.size());
+        ReadbackHelper::clearColors(expectedColors, mDisplayWidth, mDisplayHeight, mDisplayWidth);
+
+        auto layer = mLayers[1];
+        BlendMode blendMode = layer->getBlendMode();
+        float alpha = mTopLayerColor.a / 255.0f * layer->getAlpha();
+        if (blendMode == BlendMode::NONE) {
+            for (auto& expectedColor : expectedColors) {
+                expectedColor.r = mTopLayerColor.r * static_cast<int8_t>(layer->getAlpha());
+                expectedColor.g = mTopLayerColor.g * static_cast<int8_t>(layer->getAlpha());
+                expectedColor.b = mTopLayerColor.b * static_cast<int8_t>(layer->getAlpha());
+                expectedColor.a = static_cast<int8_t>(alpha * 255.0);
+            }
+        } else if (blendMode == BlendMode::PREMULTIPLIED) {
+            for (auto& expectedColor : expectedColors) {
+                expectedColor.r = static_cast<int8_t>(
+                        mTopLayerColor.r * static_cast<int8_t>(layer->getAlpha()) +
+                        mBackgroundColor.r * (1.0 - alpha));
+                expectedColor.g = static_cast<int8_t>(mTopLayerColor.g * layer->getAlpha() +
+                                                      mBackgroundColor.g * (1.0 - alpha));
+                expectedColor.b = static_cast<int8_t>(mTopLayerColor.b * layer->getAlpha() +
+                                                      mBackgroundColor.b * (1.0 - alpha));
+                expectedColor.a = static_cast<int8_t>(alpha + mBackgroundColor.a * (1.0 - alpha));
+            }
+        } else if (blendMode == BlendMode::COVERAGE) {
+            for (auto& expectedColor : expectedColors) {
+                expectedColor.r = static_cast<int8_t>(mTopLayerColor.r * alpha +
+                                                      mBackgroundColor.r * (1.0 - alpha));
+                expectedColor.g = static_cast<int8_t>(mTopLayerColor.g * alpha +
+                                                      mBackgroundColor.g * (1.0 - alpha));
+                expectedColor.b = static_cast<int8_t>(mTopLayerColor.b * alpha +
+                                                      mBackgroundColor.b * (1.0 - alpha));
+                expectedColor.a = static_cast<int8_t>(mTopLayerColor.a * alpha +
+                                                      mBackgroundColor.a * (1.0 - alpha));
+            }
+        }
+    }
+
+  protected:
+    std::vector<std::shared_ptr<TestLayer>> mLayers;
+    Color mBackgroundColor;
+    Color mTopLayerColor;
+};
+
+TEST_P(GraphicsBlendModeCompositionTest, None) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+
+        setBackgroundColor(BLACK);
+        setTopLayerColor(TRANSLUCENT_RED);
+        setUpLayers(BlendMode::NONE);
+        setExpectedColors(expectedColors);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+        writeLayers(mLayers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(mLayers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsBlendModeCompositionTest, Coverage) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+
+        setBackgroundColor(BLACK);
+        setTopLayerColor(TRANSLUCENT_RED);
+
+        setUpLayers(BlendMode::COVERAGE);
+        setExpectedColors(expectedColors);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+        writeLayers(mLayers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsBlendModeCompositionTest, Premultiplied) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+
+        setBackgroundColor(BLACK);
+        setTopLayerColor(TRANSLUCENT_RED);
+        setUpLayers(BlendMode::PREMULTIPLIED);
+        setExpectedColors(expectedColors);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+        writeLayers(mLayers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(mLayers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
+class GraphicsTransformCompositionTest : public GraphicsCompositionTest {
+  protected:
+    void SetUp() override {
+        GraphicsCompositionTest::SetUp();
+
+        auto backgroundLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        backgroundLayer->setColor({0, 0, 0, 0});
+        backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        backgroundLayer->setZOrder(0);
+
+        mSideLength = mDisplayWidth < mDisplayHeight ? mDisplayWidth : mDisplayHeight;
+        common::Rect redRect = {0, 0, mSideLength / 2, mSideLength / 2};
+        common::Rect blueRect = {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength};
+
+        mLayer = std::make_shared<TestBufferLayer>(mComposerClient, mGraphicBuffer,
+                                                   *mTestRenderEngine, mPrimaryDisplay, mSideLength,
+                                                   mSideLength, PixelFormat::RGBA_8888);
+        mLayer->setDisplayFrame({0, 0, mSideLength, mSideLength});
+        mLayer->setZOrder(10);
+
+        std::vector<Color> baseColors(static_cast<size_t>(mSideLength * mSideLength));
+        ReadbackHelper::fillColorsArea(baseColors, mSideLength, redRect, RED);
+        ReadbackHelper::fillColorsArea(baseColors, mSideLength, blueRect, BLUE);
+        ASSERT_NO_FATAL_FAILURE(mLayer->setBuffer(baseColors));
+        mLayers = {backgroundLayer, mLayer};
+    }
+
+  protected:
+    std::shared_ptr<TestBufferLayer> mLayer;
+    std::vector<std::shared_ptr<TestLayer>> mLayers;
+    int mSideLength;
+};
+
+TEST_P(GraphicsTransformCompositionTest, FLIP_H) {
+    for (ColorMode mode : mTestColorModes) {
+        auto error =
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC);
+        if (!error.isOk() &&
+            (error.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED ||
+             error.getServiceSpecificError() == IComposerClient::EX_BAD_PARAMETER)) {
+            SUCCEED() << "ColorMode not supported, skip test";
+            return;
+        }
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+        mLayer->setTransform(Transform::FLIP_H);
+        mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {mSideLength / 2, 0, mSideLength, mSideLength / 2}, RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mSideLength / 2, mSideLength / 2, mSideLength}, BLUE);
+
+        writeLayers(mLayers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(mLayers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsTransformCompositionTest, FLIP_V) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        mLayer->setTransform(Transform::FLIP_V);
+        mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, mSideLength / 2, mSideLength / 2, mSideLength}, RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {mSideLength / 2, 0, mSideLength, mSideLength / 2}, BLUE);
+
+        writeLayers(mLayers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(mLayers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
+TEST_P(GraphicsTransformCompositionTest, ROT_180) {
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+            return;
+        }
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
+                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        mLayer->setTransform(Transform::ROT_180);
+        mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength},
+                                       RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
+                                       {0, 0, mSideLength / 2, mSideLength / 2}, BLUE);
+
+        writeLayers(mLayers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(mLayers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsCompositionTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsCompositionTest,
+        testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
+        ::android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsBlendModeCompositionTest);
+INSTANTIATE_TEST_SUITE_P(BlendMode, GraphicsBlendModeCompositionTest,
+                         testing::Combine(testing::ValuesIn(::android::getAidlHalInstanceNames(
+                                                  IComposer::descriptor)),
+                                          testing::Values("0.2", "1.0")));
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsTransformCompositionTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsTransformCompositionTest,
+        testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
+        ::android::PrintInstanceNameToString);
+
+}  // namespace
+}  // namespace aidl::android::hardware::graphics::composer3::vts
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
new file mode 100644
index 0000000..4dbe191
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -0,0 +1,2079 @@
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/graphics/common/BlendMode.h>
+#include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include <aidl/android/hardware/graphics/common/FRect.h>
+#include <aidl/android/hardware/graphics/common/Rect.h>
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+#include <aidl/android/hardware/graphics/composer3/IComposer.h>
+#include <android-base/properties.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/hardware/graphics/composer3/ComposerClientReader.h>
+#include <android/hardware/graphics/composer3/ComposerClientWriter.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
+#include <algorithm>
+#include <numeric>
+#include <regex>
+#include <string>
+#include <thread>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include "composer-vts/include/GraphicsComposerCallback.h"
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop  // ignored "-Wconversion
+
+#undef LOG_TAG
+#define LOG_TAG "VtsHalGraphicsComposer3_TargetTest"
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+namespace {
+
+using namespace std::chrono_literals;
+
+using ::android::GraphicBuffer;
+using ::android::sp;
+
+class VtsDisplay {
+  public:
+    VtsDisplay(int64_t displayId, int32_t displayWidth, int32_t displayHeight)
+        : mDisplayId(displayId), mDisplayWidth(displayWidth), mDisplayHeight(displayHeight) {}
+
+    int64_t get() const { return mDisplayId; }
+
+    FRect getCrop() const {
+        return {0, 0, static_cast<float>(mDisplayWidth), static_cast<float>(mDisplayHeight)};
+    }
+
+    Rect getFrameRect() const { return {0, 0, mDisplayWidth, mDisplayHeight}; }
+
+    void setDimensions(int32_t displayWidth, int32_t displayHeight) {
+        mDisplayWidth = displayWidth;
+        mDisplayHeight = displayHeight;
+    }
+
+  private:
+    const int64_t mDisplayId;
+    int32_t mDisplayWidth;
+    int32_t mDisplayHeight;
+};
+
+class GraphicsComposerAidlTest : public ::testing::TestWithParam<std::string> {
+  protected:
+    void SetUp() override {
+        std::string name = GetParam();
+        ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
+        ASSERT_NE(binder, nullptr);
+        ASSERT_NO_FATAL_FAILURE(mComposer = IComposer::fromBinder(binder));
+        ASSERT_NE(mComposer, nullptr);
+        ASSERT_NO_FATAL_FAILURE(mComposer->createClient(&mComposerClient));
+
+        mComposerCallback = ::ndk::SharedRefBase::make<GraphicsComposerCallback>();
+        EXPECT_TRUE(mComposerClient->registerCallback(mComposerCallback).isOk());
+
+        // assume the first displays are built-in and are never removed
+        mDisplays = waitForDisplays();
+        mPrimaryDisplay = mDisplays[0].get();
+        ASSERT_NO_FATAL_FAILURE(mInvalidDisplayId = GetInvalidDisplayId());
+
+        int32_t activeConfig;
+        EXPECT_TRUE(mComposerClient->getActiveConfig(mPrimaryDisplay, &activeConfig).isOk());
+        EXPECT_TRUE(mComposerClient
+                            ->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+                                                  DisplayAttribute::WIDTH, &mDisplayWidth)
+                            .isOk());
+        EXPECT_TRUE(mComposerClient
+                            ->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+                                                  DisplayAttribute::HEIGHT, &mDisplayHeight)
+                            .isOk());
+
+        // explicitly disable vsync
+        for (const auto& display : mDisplays) {
+            EXPECT_TRUE(mComposerClient->setVsyncEnabled(display.get(), false).isOk());
+        }
+        mComposerCallback->setVsyncAllowed(false);
+    }
+
+    void TearDown() override {
+        destroyAllLayers();
+        if (mComposerCallback != nullptr) {
+            EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidVsyncPeriodChangeCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidSeamlessPossibleCount());
+        }
+    }
+
+    void Test_setContentTypeForDisplay(const int64_t& display,
+                                       const std::vector<ContentType>& capabilities,
+                                       const ContentType& contentType, const char* contentTypeStr) {
+        const bool contentTypeSupport = std::find(capabilities.begin(), capabilities.end(),
+                                                  contentType) != capabilities.end();
+
+        if (!contentTypeSupport) {
+            EXPECT_EQ(IComposerClient::EX_UNSUPPORTED,
+                      mComposerClient->setContentType(display, contentType)
+                              .getServiceSpecificError());
+            GTEST_SUCCEED() << contentTypeStr << " content type is not supported on display "
+                            << std::to_string(display) << ", skipping test";
+            return;
+        }
+
+        EXPECT_TRUE(mComposerClient->setContentType(display, contentType).isOk());
+        EXPECT_TRUE(mComposerClient->setContentType(display, ContentType::NONE).isOk());
+    }
+
+    void Test_setContentType(const ContentType& contentType, const char* contentTypeStr) {
+        for (const auto& display : mDisplays) {
+            std::vector<ContentType> supportedContentTypes;
+            const auto error = mComposerClient->getSupportedContentTypes(display.get(),
+                                                                         &supportedContentTypes);
+            EXPECT_TRUE(error.isOk());
+
+            Test_setContentTypeForDisplay(display.get(), supportedContentTypes, contentType,
+                                          contentTypeStr);
+        }
+    }
+
+    int64_t createLayer(const VtsDisplay& display) {
+        int64_t layer;
+        EXPECT_TRUE(mComposerClient->createLayer(display.get(), kBufferSlotCount, &layer).isOk());
+
+        auto resourceIt = mDisplayResources.find(display.get());
+        if (resourceIt == mDisplayResources.end()) {
+            resourceIt = mDisplayResources.insert({display.get(), DisplayResource(false)}).first;
+        }
+
+        EXPECT_TRUE(resourceIt->second.layers.insert(layer).second)
+                << "duplicated layer id " << layer;
+
+        return layer;
+    }
+
+    void destroyAllLayers() {
+        for (const auto& it : mDisplayResources) {
+            auto display = it.first;
+            const DisplayResource& resource = it.second;
+
+            for (auto layer : resource.layers) {
+                const auto error = mComposerClient->destroyLayer(display, layer);
+                EXPECT_TRUE(error.isOk());
+            }
+
+            if (resource.isVirtual) {
+                const auto error = mComposerClient->destroyVirtualDisplay(display);
+                EXPECT_TRUE(error.isOk());
+            }
+        }
+        mDisplayResources.clear();
+    }
+
+    void destroyLayer(const VtsDisplay& display, int64_t layer) {
+        auto const error = mComposerClient->destroyLayer(display.get(), layer);
+        ASSERT_TRUE(error.isOk()) << "failed to destroy layer " << layer;
+
+        auto resourceIt = mDisplayResources.find(display.get());
+        ASSERT_NE(mDisplayResources.end(), resourceIt);
+        resourceIt->second.layers.erase(layer);
+    }
+
+    // returns an invalid display id (one that has not been registered to a
+    // display.  Currently assuming that a device will never have close to
+    // std::numeric_limit<uint64_t>::max() displays registered while running tests
+    int64_t GetInvalidDisplayId() {
+        int64_t id = std::numeric_limits<int64_t>::max();
+        while (id > 0) {
+            if (std::none_of(mDisplays.begin(), mDisplays.end(),
+                             [&](const VtsDisplay& display) { return id == display.get(); })) {
+                return id;
+            }
+            id--;
+        }
+
+        // Although 0 could be an invalid display, a return value of 0
+        // from GetInvalidDisplayId means all other ids are in use, a condition which
+        // we are assuming a device will never have
+        EXPECT_NE(0, id);
+        return id;
+    }
+
+    std::vector<VtsDisplay> waitForDisplays() {
+        while (true) {
+            // Sleep for a small period of time to allow all built-in displays
+            // to post hotplug events
+            std::this_thread::sleep_for(5ms);
+            std::vector<int64_t> displays = mComposerCallback->getDisplays();
+            if (displays.empty()) {
+                continue;
+            }
+
+            std::vector<VtsDisplay> vtsDisplays;
+            vtsDisplays.reserve(displays.size());
+            for (int64_t display : displays) {
+                int32_t activeConfig;
+                EXPECT_TRUE(mComposerClient->getActiveConfig(display, &activeConfig).isOk());
+                int32_t displayWidth;
+                EXPECT_TRUE(mComposerClient
+                                    ->getDisplayAttribute(display, activeConfig,
+                                                          DisplayAttribute::WIDTH, &displayWidth)
+                                    .isOk());
+                int32_t displayHeight;
+                EXPECT_TRUE(mComposerClient
+                                    ->getDisplayAttribute(display, activeConfig,
+                                                          DisplayAttribute::HEIGHT, &displayHeight)
+                                    .isOk());
+                vtsDisplays.emplace_back(VtsDisplay{display, displayWidth, displayHeight});
+            }
+
+            return vtsDisplays;
+        }
+    }
+
+    // returns an invalid config id which is std::numeric_limit<int32_t>::max()
+    int32_t GetInvalidConfigId() { return IComposerClient::INVALID_CONFIGURATION; }
+
+    ndk::ScopedAStatus setActiveConfigWithConstraints(
+            VtsDisplay& display, int32_t config, const VsyncPeriodChangeConstraints& constraints,
+            VsyncPeriodChangeTimeline* timeline) {
+        auto error = mComposerClient->setActiveConfigWithConstraints(display.get(), config,
+                                                                     constraints, timeline);
+        if (error.isOk()) {
+            int32_t displayWidth;
+            EXPECT_TRUE(mComposerClient
+                                ->getDisplayAttribute(display.get(), config,
+                                                      DisplayAttribute::WIDTH, &displayWidth)
+                                .isOk());
+            int32_t displayHeight;
+            EXPECT_TRUE(mComposerClient
+                                ->getDisplayAttribute(display.get(), config,
+                                                      DisplayAttribute::HEIGHT, &displayHeight)
+                                .isOk());
+            display.setDimensions(displayWidth, displayHeight);
+        }
+        return error;
+    }
+
+    struct TestParameters {
+        nsecs_t delayForChange;
+        bool refreshMiss;
+    };
+
+    // Keep track of all virtual displays and layers.  When a test fails with
+    // ASSERT_*, the destructor will clean up the resources for the test.
+    struct DisplayResource {
+        DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {}
+
+        bool isVirtual;
+        std::unordered_set<int64_t> layers;
+    };
+
+    std::shared_ptr<IComposer> mComposer;
+    std::shared_ptr<IComposerClient> mComposerClient;
+    int64_t mInvalidDisplayId;
+    int64_t mPrimaryDisplay;
+    std::vector<VtsDisplay> mDisplays;
+    std::shared_ptr<GraphicsComposerCallback> mComposerCallback;
+    // use the slot count usually set by SF
+    static constexpr uint32_t kBufferSlotCount = 64;
+    std::unordered_map<int64_t, DisplayResource> mDisplayResources;
+    int32_t mDisplayWidth;
+    int32_t mDisplayHeight;
+};
+
+TEST_P(GraphicsComposerAidlTest, getDisplayCapabilitiesBadDisplay) {
+    std::vector<DisplayCapability> capabilities;
+    const auto error = mComposerClient->getDisplayCapabilities(mInvalidDisplayId, &capabilities);
+
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, getDisplayCapabilities) {
+    for (const auto& display : mDisplays) {
+        std::vector<DisplayCapability> capabilities;
+
+        EXPECT_TRUE(mComposerClient->getDisplayCapabilities(display.get(), &capabilities).isOk());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, DumpDebugInfo) {
+    std::string debugInfo;
+    EXPECT_TRUE(mComposer->dumpDebugInfo(&debugInfo).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, CreateClientSingleton) {
+    std::shared_ptr<IComposerClient> composerClient;
+    const auto error = mComposer->createClient(&composerClient);
+
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_NO_RESOURCES, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDisplayIdentificationData) {
+    DisplayIdentification displayIdentification0;
+
+    const auto error =
+            mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &displayIdentification0);
+    if (error.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
+        return;
+    }
+    ASSERT_TRUE(error.isOk()) << "failed to get display identification data";
+    ASSERT_FALSE(displayIdentification0.data.empty());
+
+    constexpr size_t kEdidBlockSize = 128;
+    ASSERT_TRUE(displayIdentification0.data.size() % kEdidBlockSize == 0)
+            << "EDID blob length is not a multiple of " << kEdidBlockSize;
+
+    const uint8_t kEdidHeader[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
+    ASSERT_TRUE(std::equal(std::begin(kEdidHeader), std::end(kEdidHeader),
+                           displayIdentification0.data.begin()))
+            << "EDID blob doesn't start with the fixed EDID header";
+    ASSERT_EQ(0, std::accumulate(displayIdentification0.data.begin(),
+                                 displayIdentification0.data.begin() + kEdidBlockSize,
+                                 static_cast<uint8_t>(0)))
+            << "EDID base block doesn't checksum";
+
+    DisplayIdentification displayIdentification1;
+    ASSERT_TRUE(
+            mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &displayIdentification1)
+                    .isOk());
+
+    ASSERT_EQ(displayIdentification0.port, displayIdentification1.port) << "ports are not stable";
+    ASSERT_TRUE(displayIdentification0.data.size() == displayIdentification1.data.size() &&
+                std::equal(displayIdentification0.data.begin(), displayIdentification0.data.end(),
+                           displayIdentification1.data.begin()))
+            << "data is not stable";
+}
+
+TEST_P(GraphicsComposerAidlTest, GetHdrCapabilities) {
+    HdrCapabilities hdrCapabilities;
+    const auto error = mComposerClient->getHdrCapabilities(mPrimaryDisplay, &hdrCapabilities);
+
+    ASSERT_TRUE(error.isOk());
+    ASSERT_TRUE(hdrCapabilities.maxLuminance >= hdrCapabilities.minLuminance);
+}
+
+TEST_P(GraphicsComposerAidlTest, GetPerFrameMetadataKeys) {
+    std::vector<PerFrameMetadataKey> keys;
+    const auto error = mComposerClient->getPerFrameMetadataKeys(mPrimaryDisplay, &keys);
+
+    if (error.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
+        GTEST_SUCCEED() << "getPerFrameMetadataKeys is not supported";
+        return;
+    }
+    EXPECT_TRUE(error.isOk());
+    ASSERT_TRUE(keys.size() >= 0);
+}
+
+TEST_P(GraphicsComposerAidlTest, GetReadbackBufferAttributes) {
+    ReadbackBufferAttributes readBackBufferAttributes;
+    const auto error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay,
+                                                                    &readBackBufferAttributes);
+
+    if (error.isOk()) {
+        EXPECT_EQ(EX_NONE, error.getServiceSpecificError());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, GetRenderIntents) {
+    std::vector<ColorMode> modes;
+    EXPECT_TRUE(mComposerClient->getColorModes(mPrimaryDisplay, &modes).isOk());
+    for (auto mode : modes) {
+        std::vector<RenderIntent> intents;
+        EXPECT_TRUE(mComposerClient->getRenderIntents(mPrimaryDisplay, mode, &intents).isOk());
+
+        bool isHdr;
+        switch (mode) {
+            case ColorMode::BT2100_PQ:
+            case ColorMode::BT2100_HLG:
+                isHdr = true;
+                break;
+            default:
+                isHdr = false;
+                break;
+        }
+        RenderIntent requiredIntent =
+                isHdr ? RenderIntent::TONE_MAP_COLORIMETRIC : RenderIntent::COLORIMETRIC;
+
+        auto iter = std::find(intents.cbegin(), intents.cend(), requiredIntent);
+        EXPECT_NE(intents.cend(), iter);
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, GetRenderIntentsBadDisplay) {
+    std::vector<ColorMode> modes;
+    EXPECT_TRUE(mComposerClient->getColorModes(mPrimaryDisplay, &modes).isOk());
+    for (auto mode : modes) {
+        std::vector<RenderIntent> renderIntents;
+        const auto error =
+                mComposerClient->getRenderIntents(mInvalidDisplayId, mode, &renderIntents);
+        EXPECT_FALSE(error.isOk());
+        EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, GetRenderIntentsBadParameter) {
+    std::vector<RenderIntent> renderIntents;
+    const auto error = mComposerClient->getRenderIntents(
+            mPrimaryDisplay, static_cast<ColorMode>(-1), &renderIntents);
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_PARAMETER, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetColorModes) {
+    std::vector<ColorMode> colorModes;
+    EXPECT_TRUE(mComposerClient->getColorModes(mPrimaryDisplay, &colorModes).isOk());
+
+    auto native = std::find(colorModes.cbegin(), colorModes.cend(), ColorMode::NATIVE);
+    ASSERT_NE(colorModes.cend(), native);
+}
+
+TEST_P(GraphicsComposerAidlTest, GetColorModeBadDisplay) {
+    std::vector<ColorMode> colorModes;
+    const auto error = mComposerClient->getColorModes(mInvalidDisplayId, &colorModes);
+
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, SetColorMode) {
+    std::vector<ColorMode> colorModes;
+    EXPECT_TRUE(mComposerClient->getColorModes(mPrimaryDisplay, &colorModes).isOk());
+    for (auto mode : colorModes) {
+        std::vector<RenderIntent> intents;
+        EXPECT_TRUE(mComposerClient->getRenderIntents(mPrimaryDisplay, mode, &intents).isOk())
+                << "failed to get render intents";
+        for (auto intent : intents) {
+            const auto error = mComposerClient->setColorMode(mPrimaryDisplay, mode, intent);
+            EXPECT_TRUE(error.isOk() ||
+                        IComposerClient::EX_UNSUPPORTED == error.getServiceSpecificError())
+                    << "failed to set color mode";
+        }
+    }
+
+    const auto error = mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE,
+                                                     RenderIntent::COLORIMETRIC);
+    EXPECT_TRUE(error.isOk() || IComposerClient::EX_UNSUPPORTED == error.getServiceSpecificError())
+            << "failed to set color mode";
+}
+
+TEST_P(GraphicsComposerAidlTest, SetColorModeBadDisplay) {
+    std::vector<ColorMode> colorModes;
+    EXPECT_TRUE(mComposerClient->getColorModes(mPrimaryDisplay, &colorModes).isOk());
+    for (auto mode : colorModes) {
+        std::vector<RenderIntent> intents;
+        EXPECT_TRUE(mComposerClient->getRenderIntents(mPrimaryDisplay, mode, &intents).isOk())
+                << "failed to get render intents";
+        for (auto intent : intents) {
+            auto const error = mComposerClient->setColorMode(mInvalidDisplayId, mode, intent);
+
+            EXPECT_FALSE(error.isOk());
+            ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+        }
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, SetColorModeBadParameter) {
+    const auto colorModeError = mComposerClient->setColorMode(
+            mPrimaryDisplay, static_cast<ColorMode>(-1), RenderIntent::COLORIMETRIC);
+
+    EXPECT_FALSE(colorModeError.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_PARAMETER, colorModeError.getServiceSpecificError());
+
+    const auto renderIntentError = mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE,
+                                                                 static_cast<RenderIntent>(-1));
+
+    EXPECT_FALSE(renderIntentError.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_PARAMETER, renderIntentError.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDisplayedContentSamplingAttributes) {
+    int constexpr invalid = -1;
+
+    DisplayContentSamplingAttributes format;
+    auto error = mComposerClient->getDisplayedContentSamplingAttributes(mPrimaryDisplay, &format);
+
+    if (error.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
+        SUCCEED() << "Device does not support optional extension. Test skipped";
+        return;
+    }
+
+    EXPECT_TRUE(error.isOk());
+    EXPECT_NE(format.format, static_cast<common::PixelFormat>(invalid));
+    EXPECT_NE(format.dataspace, static_cast<common::Dataspace>(invalid));
+    EXPECT_NE(format.componentMask, static_cast<FormatColorComponent>(invalid));
+};
+
+TEST_P(GraphicsComposerAidlTest, SetDisplayedContentSamplingEnabled) {
+    auto const maxFrames = 10;
+    FormatColorComponent enableAllComponents = FormatColorComponent::FORMAT_COMPONENT_0;
+    auto error = mComposerClient->setDisplayedContentSamplingEnabled(
+            mPrimaryDisplay, true, enableAllComponents, maxFrames);
+    if (error.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
+        SUCCEED() << "Device does not support optional extension. Test skipped";
+        return;
+    }
+    EXPECT_TRUE(error.isOk());
+
+    error = mComposerClient->setDisplayedContentSamplingEnabled(mPrimaryDisplay, false,
+                                                                enableAllComponents, maxFrames);
+    EXPECT_TRUE(error.isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDisplayedContentSample) {
+    DisplayContentSamplingAttributes displayContentSamplingAttributes;
+    int constexpr invalid = -1;
+    displayContentSamplingAttributes.format = static_cast<common::PixelFormat>(invalid);
+    displayContentSamplingAttributes.dataspace = static_cast<common::Dataspace>(invalid);
+    displayContentSamplingAttributes.componentMask = static_cast<FormatColorComponent>(invalid);
+    auto error = mComposerClient->getDisplayedContentSamplingAttributes(
+            mPrimaryDisplay, &displayContentSamplingAttributes);
+    if (error.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
+        SUCCEED() << "Sampling attributes aren't supported on this device, test skipped";
+        return;
+    }
+
+    int64_t maxFrames = 10;
+    int64_t timestamp = 0;
+    int64_t frameCount = 0;
+    DisplayContentSample displayContentSample;
+    error = mComposerClient->getDisplayedContentSample(mPrimaryDisplay, maxFrames, timestamp,
+                                                       &displayContentSample);
+    if (error.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
+        SUCCEED() << "Device does not support optional extension. Test skipped";
+        return;
+    }
+
+    EXPECT_TRUE(error.isOk());
+    EXPECT_LE(frameCount, maxFrames);
+    std::vector<std::vector<int64_t>> histogram = {
+            displayContentSample.sampleComponent0, displayContentSample.sampleComponent1,
+            displayContentSample.sampleComponent2, displayContentSample.sampleComponent3};
+
+    for (size_t i = 0; i < histogram.size(); i++) {
+        const bool shouldHaveHistogram =
+                static_cast<int>(displayContentSamplingAttributes.componentMask) & (1 << i);
+        EXPECT_EQ(shouldHaveHistogram, !histogram[i].empty());
+    }
+}
+
+/*
+ * Test that if brightness operations are supported, setDisplayBrightness works as expected.
+ */
+TEST_P(GraphicsComposerAidlTest, setDisplayBrightness) {
+    std::vector<DisplayCapability> capabilities;
+    auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities);
+    ASSERT_TRUE(error.isOk());
+    bool brightnessSupport = std::find(capabilities.begin(), capabilities.end(),
+                                       DisplayCapability::BRIGHTNESS) != capabilities.end();
+    if (!brightnessSupport) {
+        EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 0.5f)
+                          .getServiceSpecificError(),
+                  IComposerClient::EX_UNSUPPORTED);
+        GTEST_SUCCEED() << "Brightness operations are not supported";
+        return;
+    }
+
+    EXPECT_TRUE(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 0.0f).isOk());
+    EXPECT_TRUE(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 0.5f).isOk());
+    EXPECT_TRUE(mComposerClient->setDisplayBrightness(mPrimaryDisplay, 1.0f).isOk());
+    EXPECT_TRUE(mComposerClient->setDisplayBrightness(mPrimaryDisplay, -1.0f).isOk());
+
+    error = mComposerClient->setDisplayBrightness(mPrimaryDisplay, +2.0f);
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(error.getServiceSpecificError(), IComposerClient::EX_BAD_PARAMETER);
+
+    error = mComposerClient->setDisplayBrightness(mPrimaryDisplay, -2.0f);
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(error.getServiceSpecificError(), IComposerClient::EX_BAD_PARAMETER);
+}
+
+TEST_P(GraphicsComposerAidlTest, getDisplayConnectionType) {
+    DisplayConnectionType type;
+    EXPECT_FALSE(mComposerClient->getDisplayConnectionType(mInvalidDisplayId, &type).isOk());
+    for (const auto& display : mDisplays) {
+        EXPECT_TRUE(mComposerClient->getDisplayConnectionType(display.get(), &type).isOk());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, getDisplayAttribute) {
+    for (const auto& display : mDisplays) {
+        std::vector<int32_t> configs;
+        EXPECT_TRUE(mComposerClient->getDisplayConfigs(display.get(), &configs).isOk());
+        for (const auto& config : configs) {
+            const std::array<DisplayAttribute, 4> requiredAttributes = {{
+                    DisplayAttribute::WIDTH,
+                    DisplayAttribute::HEIGHT,
+                    DisplayAttribute::VSYNC_PERIOD,
+                    DisplayAttribute::CONFIG_GROUP,
+            }};
+            int32_t value;
+            for (const auto& attribute : requiredAttributes) {
+                EXPECT_TRUE(mComposerClient
+                                    ->getDisplayAttribute(display.get(), config, attribute, &value)
+                                    .isOk());
+                EXPECT_NE(-1, value);
+            }
+
+            const std::array<DisplayAttribute, 2> optionalAttributes = {{
+                    DisplayAttribute::DPI_X,
+                    DisplayAttribute::DPI_Y,
+            }};
+            for (const auto& attribute : optionalAttributes) {
+                const auto error = mComposerClient->getDisplayAttribute(display.get(), config,
+                                                                        attribute, &value);
+                if (error.isOk()) {
+                    EXPECT_EQ(EX_NONE, error.getServiceSpecificError());
+                } else {
+                    EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
+                }
+            }
+        }
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, checkConfigsAreValid) {
+    for (const auto& display : mDisplays) {
+        std::vector<int32_t> configs;
+        EXPECT_TRUE(mComposerClient->getDisplayConfigs(display.get(), &configs).isOk());
+
+        EXPECT_FALSE(std::any_of(configs.begin(), configs.end(), [](auto config) {
+            return config == IComposerClient::INVALID_CONFIGURATION;
+        }));
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, getDisplayAttributeConfigsInAGroupDifferOnlyByVsyncPeriod) {
+    struct Resolution {
+        int32_t width;
+        int32_t height;
+    };
+    struct Dpi {
+        int32_t x;
+        int32_t y;
+    };
+    for (const auto& display : mDisplays) {
+        std::vector<int32_t> configs;
+        EXPECT_TRUE(mComposerClient->getDisplayConfigs(display.get(), &configs).isOk());
+        std::unordered_map<int32_t, Resolution> configGroupToResolutionMap;
+        std::unordered_map<int32_t, Dpi> configGroupToDpiMap;
+        for (const auto& config : configs) {
+            int32_t configGroup = -1;
+            EXPECT_TRUE(mComposerClient
+                                ->getDisplayAttribute(display.get(), config,
+                                                      DisplayAttribute::CONFIG_GROUP, &configGroup)
+                                .isOk());
+            int32_t width = -1;
+            EXPECT_TRUE(mComposerClient
+                                ->getDisplayAttribute(display.get(), config,
+                                                      DisplayAttribute::WIDTH, &width)
+                                .isOk());
+            int32_t height = -1;
+            EXPECT_TRUE(mComposerClient
+                                ->getDisplayAttribute(display.get(), config,
+                                                      DisplayAttribute::HEIGHT, &height)
+                                .isOk());
+            if (configGroupToResolutionMap.find(configGroup) == configGroupToResolutionMap.end()) {
+                configGroupToResolutionMap[configGroup] = {width, height};
+            }
+            EXPECT_EQ(configGroupToResolutionMap[configGroup].width, width);
+            EXPECT_EQ(configGroupToResolutionMap[configGroup].height, height);
+
+            int32_t dpiX = -1;
+            mComposerClient->getDisplayAttribute(display.get(), config, DisplayAttribute::DPI_X,
+                                                 &dpiX);
+
+            int32_t dpiY = -1;
+            mComposerClient->getDisplayAttribute(display.get(), config, DisplayAttribute::DPI_Y,
+                                                 &dpiY);
+            if (dpiX == -1 && dpiY == -1) {
+                continue;
+            }
+
+            if (configGroupToDpiMap.find(configGroup) == configGroupToDpiMap.end()) {
+                configGroupToDpiMap[configGroup] = {dpiX, dpiY};
+            }
+            EXPECT_EQ(configGroupToDpiMap[configGroup].x, dpiX);
+            EXPECT_EQ(configGroupToDpiMap[configGroup].y, dpiY);
+        }
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, getDisplayVsyncPeriod_BadDisplay) {
+    int32_t vsyncPeriodNanos;
+    const auto error = mComposerClient->getDisplayVsyncPeriod(mInvalidDisplayId, &vsyncPeriodNanos);
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, setActiveConfigWithConstraints_BadDisplay) {
+    VsyncPeriodChangeTimeline timeline;
+    VsyncPeriodChangeConstraints constraints;
+
+    constraints.seamlessRequired = false;
+    constraints.desiredTimeNanos = systemTime();
+    int32_t config = 0;
+    auto const error = mComposerClient->setActiveConfigWithConstraints(mInvalidDisplayId, config,
+                                                                       constraints, &timeline);
+
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, setActiveConfigWithConstraints_BadConfig) {
+    VsyncPeriodChangeTimeline timeline;
+    VsyncPeriodChangeConstraints constraints;
+
+    constraints.seamlessRequired = false;
+    constraints.desiredTimeNanos = systemTime();
+
+    for (VtsDisplay& display : mDisplays) {
+        int32_t invalidConfigId = GetInvalidConfigId();
+        const auto error =
+                setActiveConfigWithConstraints(display, invalidConfigId, constraints, &timeline);
+        EXPECT_FALSE(error.isOk());
+        EXPECT_EQ(IComposerClient::EX_BAD_CONFIG, error.getServiceSpecificError());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, setAutoLowLatencyModeBadDisplay) {
+    EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY,
+              mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, true)
+                      .getServiceSpecificError());
+    EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY,
+              mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, false)
+                      .getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, setAutoLowLatencyMode) {
+    for (const auto& display : mDisplays) {
+        std::vector<DisplayCapability> capabilities;
+        const auto error = mComposerClient->getDisplayCapabilities(display.get(), &capabilities);
+        EXPECT_TRUE(error.isOk());
+
+        const bool allmSupport =
+                std::find(capabilities.begin(), capabilities.end(),
+                          DisplayCapability::AUTO_LOW_LATENCY_MODE) != capabilities.end();
+
+        if (!allmSupport) {
+            const auto errorIsOn = mComposerClient->setAutoLowLatencyMode(display.get(), true);
+            EXPECT_FALSE(errorIsOn.isOk());
+            EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, errorIsOn.getServiceSpecificError());
+            const auto errorIsOff = mComposerClient->setAutoLowLatencyMode(display.get(), false);
+            EXPECT_FALSE(errorIsOff.isOk());
+            EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, errorIsOff.getServiceSpecificError());
+            GTEST_SUCCEED() << "Auto Low Latency Mode is not supported on display "
+                            << std::to_string(display.get()) << ", skipping test";
+            return;
+        }
+
+        EXPECT_TRUE(mComposerClient->setAutoLowLatencyMode(display.get(), true).isOk());
+        EXPECT_TRUE(mComposerClient->setAutoLowLatencyMode(display.get(), false).isOk());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, getSupportedContentTypesBadDisplay) {
+    std::vector<ContentType> supportedContentTypes;
+    const auto error =
+            mComposerClient->getSupportedContentTypes(mInvalidDisplayId, &supportedContentTypes);
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, getSupportedContentTypes) {
+    std::vector<ContentType> supportedContentTypes;
+    for (const auto& display : mDisplays) {
+        supportedContentTypes.clear();
+        const auto error =
+                mComposerClient->getSupportedContentTypes(display.get(), &supportedContentTypes);
+
+        ASSERT_TRUE(error.isOk());
+
+        const bool noneSupported =
+                std::find(supportedContentTypes.begin(), supportedContentTypes.end(),
+                          ContentType::NONE) != supportedContentTypes.end();
+        EXPECT_FALSE(noneSupported);
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, setContentTypeNoneAlwaysAccepted) {
+    for (const auto& display : mDisplays) {
+        const auto error = mComposerClient->setContentType(display.get(), ContentType::NONE);
+        EXPECT_TRUE(error.isOk());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, setContentTypeBadDisplay) {
+    constexpr ContentType types[] = {ContentType::NONE, ContentType::GRAPHICS, ContentType::PHOTO,
+                                     ContentType::CINEMA, ContentType::GAME};
+    for (const auto& type : types) {
+        auto const error = mComposerClient->setContentType(mInvalidDisplayId, type);
+
+        EXPECT_FALSE(error.isOk());
+        EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, setGraphicsContentType) {
+    Test_setContentType(ContentType::GRAPHICS, "GRAPHICS");
+}
+
+TEST_P(GraphicsComposerAidlTest, setPhotoContentType) {
+    Test_setContentType(ContentType::PHOTO, "PHOTO");
+}
+
+TEST_P(GraphicsComposerAidlTest, setCinemaContentType) {
+    Test_setContentType(ContentType::CINEMA, "CINEMA");
+}
+
+TEST_P(GraphicsComposerAidlTest, setGameContentType) {
+    Test_setContentType(ContentType::GAME, "GAME");
+}
+
+TEST_P(GraphicsComposerAidlTest, CreateVirtualDisplay) {
+    int32_t maxVirtualDisplayCount;
+    EXPECT_TRUE(mComposerClient->getMaxVirtualDisplayCount(&maxVirtualDisplayCount).isOk());
+    if (maxVirtualDisplayCount == 0) {
+        GTEST_SUCCEED() << "no virtual display support";
+        return;
+    }
+
+    VirtualDisplay virtualDisplay;
+
+    EXPECT_TRUE(mComposerClient
+                        ->createVirtualDisplay(64, 64, common::PixelFormat::IMPLEMENTATION_DEFINED,
+                                               kBufferSlotCount, &virtualDisplay)
+                        .isOk());
+
+    ASSERT_TRUE(mDisplayResources.insert({virtualDisplay.display, DisplayResource(true)}).second)
+            << "duplicated virtual display id " << virtualDisplay.display;
+
+    EXPECT_TRUE(mComposerClient->destroyVirtualDisplay(virtualDisplay.display).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, DestroyVirtualDisplayBadDisplay) {
+    int32_t maxDisplayCount = 0;
+    EXPECT_TRUE(mComposerClient->getMaxVirtualDisplayCount(&maxDisplayCount).isOk());
+    if (maxDisplayCount == 0) {
+        GTEST_SUCCEED() << "no virtual display support";
+        return;
+    }
+    const auto error = mComposerClient->destroyVirtualDisplay(mInvalidDisplayId);
+
+    EXPECT_FALSE(error.isOk());
+    ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, CreateLayer) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    EXPECT_TRUE(mComposerClient->destroyLayer(mPrimaryDisplay, layer).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, CreateLayerBadDisplay) {
+    int64_t layer;
+    const auto error = mComposerClient->createLayer(mInvalidDisplayId, kBufferSlotCount, &layer);
+
+    EXPECT_FALSE(error.isOk());
+    ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, DestroyLayerBadDisplay) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    const auto error = mComposerClient->destroyLayer(mInvalidDisplayId, layer);
+
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+    EXPECT_TRUE(mComposerClient->destroyLayer(mPrimaryDisplay, layer).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, DestroyLayerBadLayerError) {
+    // We haven't created any layers yet, so any id should be invalid
+    const auto error = mComposerClient->destroyLayer(mPrimaryDisplay, 1);
+
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_LAYER, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetActiveConfigBadDisplay) {
+    int32_t config;
+    const auto error = mComposerClient->getActiveConfig(mInvalidDisplayId, &config);
+
+    EXPECT_FALSE(error.isOk());
+    ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDisplayConfig) {
+    std::vector<int32_t> configs;
+    EXPECT_TRUE(mComposerClient->getDisplayConfigs(mPrimaryDisplay, &configs).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDisplayConfigBadDisplay) {
+    std::vector<int32_t> configs;
+    const auto error = mComposerClient->getDisplayConfigs(mInvalidDisplayId, &configs);
+
+    EXPECT_FALSE(error.isOk());
+    ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDisplayName) {
+    std::string displayName;
+    EXPECT_TRUE(mComposerClient->getDisplayName(mPrimaryDisplay, &displayName).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, SetClientTargetSlotCount) {
+    EXPECT_TRUE(
+            mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount).isOk());
+}
+
+TEST_P(GraphicsComposerAidlTest, SetActiveConfig) {
+    std::vector<int32_t> configs;
+    EXPECT_TRUE(mComposerClient->getDisplayConfigs(mPrimaryDisplay, &configs).isOk());
+    for (auto config : configs) {
+        EXPECT_TRUE(mComposerClient->setActiveConfig(mPrimaryDisplay, config).isOk());
+        int32_t config1;
+        EXPECT_TRUE(mComposerClient->getActiveConfig(mPrimaryDisplay, &config1).isOk());
+        EXPECT_EQ(config, config1);
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, SetActiveConfigPowerCycle) {
+    EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF).isOk());
+    EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON).isOk());
+
+    std::vector<int32_t> configs;
+    EXPECT_TRUE(mComposerClient->getDisplayConfigs(mPrimaryDisplay, &configs).isOk());
+    for (auto config : configs) {
+        EXPECT_TRUE(mComposerClient->setActiveConfig(mPrimaryDisplay, config).isOk());
+        int32_t config1;
+        EXPECT_TRUE(mComposerClient->getActiveConfig(mPrimaryDisplay, &config1).isOk());
+        EXPECT_EQ(config, config1);
+
+        EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF).isOk());
+        EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON).isOk());
+        EXPECT_TRUE(mComposerClient->getActiveConfig(mPrimaryDisplay, &config1).isOk());
+        EXPECT_EQ(config, config1);
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, SetPowerModeUnsupported) {
+    std::vector<DisplayCapability> capabilities;
+    auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities);
+    ASSERT_TRUE(error.isOk());
+    const bool isDozeSupported = std::find(capabilities.begin(), capabilities.end(),
+                                           DisplayCapability::DOZE) != capabilities.end();
+    const bool isSuspendSupported = std::find(capabilities.begin(), capabilities.end(),
+                                              DisplayCapability::SUSPEND) != capabilities.end();
+    if (!isDozeSupported) {
+        error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::DOZE);
+        EXPECT_FALSE(error.isOk());
+        EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
+
+        error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::DOZE_SUSPEND);
+        EXPECT_FALSE(error.isOk());
+        EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
+    }
+
+    if (!isSuspendSupported) {
+        error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON_SUSPEND);
+        EXPECT_FALSE(error.isOk());
+        EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
+
+        error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::DOZE_SUSPEND);
+        EXPECT_FALSE(error.isOk());
+        EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, SetVsyncEnabled) {
+    mComposerCallback->setVsyncAllowed(true);
+
+    EXPECT_TRUE(mComposerClient->setVsyncEnabled(mPrimaryDisplay, true).isOk());
+    usleep(60 * 1000);
+    EXPECT_TRUE(mComposerClient->setVsyncEnabled(mPrimaryDisplay, false).isOk());
+
+    mComposerCallback->setVsyncAllowed(false);
+}
+
+TEST_P(GraphicsComposerAidlTest, SetPowerMode) {
+    std::vector<DisplayCapability> capabilities;
+    const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities);
+    ASSERT_TRUE(error.isOk());
+    const bool isDozeSupported = std::find(capabilities.begin(), capabilities.end(),
+                                           DisplayCapability::DOZE) != capabilities.end();
+    const bool isSuspendSupported = std::find(capabilities.begin(), capabilities.end(),
+                                              DisplayCapability::SUSPEND) != capabilities.end();
+
+    std::vector<PowerMode> modes;
+    modes.push_back(PowerMode::OFF);
+    modes.push_back(PowerMode::ON);
+
+    if (isSuspendSupported) {
+        modes.push_back(PowerMode::ON_SUSPEND);
+    }
+
+    if (isDozeSupported) {
+        modes.push_back(PowerMode::DOZE);
+    }
+
+    if (isSuspendSupported && isDozeSupported) {
+        modes.push_back(PowerMode::DOZE_SUSPEND);
+    }
+
+    for (auto mode : modes) {
+        EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, SetPowerModeVariations) {
+    std::vector<DisplayCapability> capabilities;
+    const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities);
+    ASSERT_TRUE(error.isOk());
+    const bool isDozeSupported = std::find(capabilities.begin(), capabilities.end(),
+                                           DisplayCapability::DOZE) != capabilities.end();
+    const bool isSuspendSupported = std::find(capabilities.begin(), capabilities.end(),
+                                              DisplayCapability::SUSPEND) != capabilities.end();
+
+    std::vector<PowerMode> modes;
+
+    modes.push_back(PowerMode::OFF);
+    modes.push_back(PowerMode::ON);
+    modes.push_back(PowerMode::OFF);
+    for (auto mode : modes) {
+        EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
+    }
+    modes.clear();
+
+    modes.push_back(PowerMode::OFF);
+    modes.push_back(PowerMode::OFF);
+    for (auto mode : modes) {
+        EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
+    }
+    modes.clear();
+
+    modes.push_back(PowerMode::ON);
+    modes.push_back(PowerMode::ON);
+    for (auto mode : modes) {
+        EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
+    }
+    modes.clear();
+
+    if (isSuspendSupported) {
+        modes.push_back(PowerMode::ON_SUSPEND);
+        modes.push_back(PowerMode::ON_SUSPEND);
+        for (auto mode : modes) {
+            EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
+        }
+        modes.clear();
+    }
+
+    if (isDozeSupported) {
+        modes.push_back(PowerMode::DOZE);
+        modes.push_back(PowerMode::DOZE);
+        for (auto mode : modes) {
+            EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
+        }
+        modes.clear();
+    }
+
+    if (isSuspendSupported && isDozeSupported) {
+        modes.push_back(PowerMode::DOZE_SUSPEND);
+        modes.push_back(PowerMode::DOZE_SUSPEND);
+        for (auto mode : modes) {
+            EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
+        }
+        modes.clear();
+    }
+}
+
+TEST_P(GraphicsComposerAidlTest, SetPowerModeBadDisplay) {
+    const auto error = mComposerClient->setPowerMode(mInvalidDisplayId, PowerMode::ON);
+
+    EXPECT_FALSE(error.isOk());
+    ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, SetPowerModeBadParameter) {
+    const auto error = mComposerClient->setPowerMode(mPrimaryDisplay, static_cast<PowerMode>(-1));
+
+    EXPECT_FALSE(error.isOk());
+    ASSERT_EQ(IComposerClient::EX_BAD_PARAMETER, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDataspaceSaturationMatrix) {
+    std::vector<float> matrix;
+    EXPECT_TRUE(
+            mComposerClient->getDataspaceSaturationMatrix(common::Dataspace::SRGB_LINEAR, &matrix)
+                    .isOk());
+
+    // the last row is known
+    ASSERT_EQ(0.0f, matrix[12]);
+    ASSERT_EQ(0.0f, matrix[13]);
+    ASSERT_EQ(0.0f, matrix[14]);
+    ASSERT_EQ(1.0f, matrix[15]);
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDataspaceSaturationMatrixBadParameter) {
+    std::vector<float> matrix;
+    const auto error =
+            mComposerClient->getDataspaceSaturationMatrix(common::Dataspace::UNKNOWN, &matrix);
+
+    EXPECT_FALSE(error.isOk());
+    EXPECT_EQ(IComposerClient::EX_BAD_PARAMETER, error.getServiceSpecificError());
+}
+
+// Tests for Command.
+class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest {
+  protected:
+    void TearDown() override {
+        const auto errors = mReader.takeErrors();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty());
+
+        ASSERT_NO_FATAL_FAILURE(GraphicsComposerAidlTest::TearDown());
+    }
+
+    void execute() {
+        const auto& commands = mWriter.getPendingCommands();
+        if (commands.empty()) {
+            mWriter.reset();
+            return;
+        }
+
+        std::vector<CommandResultPayload> results;
+        const auto status = mComposerClient->executeCommands(commands, &results);
+        ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
+
+        mReader.parse(std::move(results));
+        mWriter.reset();
+    }
+
+    static inline auto toTimePoint(nsecs_t time) {
+        return std::chrono::time_point<std::chrono::steady_clock>(std::chrono::nanoseconds(time));
+    }
+
+    void setActiveConfig(VtsDisplay& display, int32_t config) {
+        EXPECT_TRUE(mComposerClient->setActiveConfig(display.get(), config).isOk());
+        int32_t displayWidth;
+        EXPECT_TRUE(mComposerClient
+                            ->getDisplayAttribute(display.get(), config, DisplayAttribute::WIDTH,
+                                                  &displayWidth)
+                            .isOk());
+        int32_t displayHeight;
+        EXPECT_TRUE(mComposerClient
+                            ->getDisplayAttribute(display.get(), config, DisplayAttribute::HEIGHT,
+                                                  &displayHeight)
+                            .isOk());
+        display.setDimensions(displayWidth, displayHeight);
+    }
+
+    void forEachTwoConfigs(int64_t display, std::function<void(int32_t, int32_t)> func) {
+        std::vector<int32_t> displayConfigs;
+        EXPECT_TRUE(mComposerClient->getDisplayConfigs(display, &displayConfigs).isOk());
+        for (const int32_t config1 : displayConfigs) {
+            for (const int32_t config2 : displayConfigs) {
+                if (config1 != config2) {
+                    func(config1, config2);
+                }
+            }
+        }
+    }
+
+    void waitForVsyncPeriodChange(int64_t display, const VsyncPeriodChangeTimeline& timeline,
+                                  int64_t desiredTimeNanos, int64_t oldPeriodNanos,
+                                  int64_t newPeriodNanos) {
+        const auto kChangeDeadline = toTimePoint(timeline.newVsyncAppliedTimeNanos) + 100ms;
+        while (std::chrono::steady_clock::now() <= kChangeDeadline) {
+            int32_t vsyncPeriodNanos;
+            EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos).isOk());
+            if (systemTime() <= desiredTimeNanos) {
+                EXPECT_EQ(vsyncPeriodNanos, oldPeriodNanos);
+            } else if (vsyncPeriodNanos == newPeriodNanos) {
+                break;
+            }
+            std::this_thread::sleep_for(std::chrono::nanoseconds(oldPeriodNanos));
+        }
+    }
+
+    sp<GraphicBuffer> allocate() {
+        return sp<GraphicBuffer>::make(
+                static_cast<uint32_t>(mDisplayWidth), static_cast<uint32_t>(mDisplayHeight),
+                ::android::PIXEL_FORMAT_RGBA_8888,
+                /*layerCount*/ 1,
+                (static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
+                 static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+                 static_cast<uint64_t>(common::BufferUsage::COMPOSER_OVERLAY)),
+                "VtsHalGraphicsComposer3_TargetTest");
+    }
+
+    void sendRefreshFrame(const VtsDisplay& display, const VsyncPeriodChangeTimeline* timeline) {
+        if (timeline != nullptr) {
+            // Refresh time should be before newVsyncAppliedTimeNanos
+            EXPECT_LT(timeline->refreshTimeNanos, timeline->newVsyncAppliedTimeNanos);
+
+            std::this_thread::sleep_until(toTimePoint(timeline->refreshTimeNanos));
+        }
+
+        EXPECT_TRUE(mComposerClient->setPowerMode(display.get(), PowerMode::ON).isOk());
+        EXPECT_TRUE(
+                mComposerClient
+                        ->setColorMode(display.get(), ColorMode::NATIVE, RenderIntent::COLORIMETRIC)
+                        .isOk());
+
+        int64_t layer = 0;
+        ASSERT_NO_FATAL_FAILURE(layer = createLayer(display));
+        {
+            const auto buffer = allocate();
+            ASSERT_NE(nullptr, buffer);
+            ASSERT_EQ(::android::OK, buffer->initCheck());
+            ASSERT_NE(nullptr, buffer->handle);
+
+            mWriter.setLayerCompositionType(display.get(), layer, Composition::DEVICE);
+            mWriter.setLayerDisplayFrame(display.get(), layer, display.getFrameRect());
+            mWriter.setLayerPlaneAlpha(display.get(), layer, 1);
+            mWriter.setLayerSourceCrop(display.get(), layer, display.getCrop());
+            mWriter.setLayerTransform(display.get(), layer, static_cast<Transform>(0));
+            mWriter.setLayerVisibleRegion(display.get(), layer,
+                                          std::vector<Rect>(1, display.getFrameRect()));
+            mWriter.setLayerZOrder(display.get(), layer, 10);
+            mWriter.setLayerBlendMode(display.get(), layer, BlendMode::NONE);
+            mWriter.setLayerSurfaceDamage(display.get(), layer,
+                                          std::vector<Rect>(1, display.getFrameRect()));
+            mWriter.setLayerBuffer(display.get(), layer, 0, buffer->handle, -1);
+            mWriter.setLayerDataspace(display.get(), layer, common::Dataspace::UNKNOWN);
+
+            mWriter.validateDisplay(display.get(), ComposerClientWriter::kNoTimestamp);
+            execute();
+            ASSERT_TRUE(mReader.takeErrors().empty());
+
+            mWriter.presentDisplay(display.get());
+            execute();
+            ASSERT_TRUE(mReader.takeErrors().empty());
+        }
+
+        {
+            const auto buffer = allocate();
+            ASSERT_NE(nullptr, buffer->handle);
+
+            mWriter.setLayerBuffer(display.get(), layer, 0, buffer->handle, -1);
+            mWriter.setLayerSurfaceDamage(display.get(), layer,
+                                          std::vector<Rect>(1, {0, 0, 10, 10}));
+            mWriter.validateDisplay(display.get(), ComposerClientWriter::kNoTimestamp);
+            execute();
+            ASSERT_TRUE(mReader.takeErrors().empty());
+
+            mWriter.presentDisplay(display.get());
+            execute();
+        }
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+    }
+
+    sp<::android::Fence> presentAndGetFence(
+            std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
+        mWriter.validateDisplay(mPrimaryDisplay, expectedPresentTime);
+        execute();
+        EXPECT_TRUE(mReader.takeErrors().empty());
+
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        EXPECT_TRUE(mReader.takeErrors().empty());
+
+        auto presentFence = mReader.takePresentFence(mPrimaryDisplay);
+        // take ownership
+        const int fenceOwner = presentFence.get();
+        *presentFence.getR() = -1;
+        EXPECT_NE(-1, fenceOwner);
+        return sp<::android::Fence>::make(fenceOwner);
+    }
+
+    int32_t getVsyncPeriod() {
+        int32_t activeConfig;
+        EXPECT_TRUE(mComposerClient->getActiveConfig(mPrimaryDisplay, &activeConfig).isOk());
+
+        int32_t vsyncPeriod;
+        EXPECT_TRUE(mComposerClient
+                            ->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+                                                  DisplayAttribute::VSYNC_PERIOD, &vsyncPeriod)
+                            .isOk());
+        return vsyncPeriod;
+    }
+
+    int64_t createOnScreenLayer() {
+        const int64_t layer = createLayer(mDisplays[0]);
+        mWriter.setLayerCompositionType(mPrimaryDisplay, layer, Composition::DEVICE);
+        mWriter.setLayerDisplayFrame(mPrimaryDisplay, layer, {0, 0, mDisplayWidth, mDisplayHeight});
+        mWriter.setLayerPlaneAlpha(mPrimaryDisplay, layer, 1);
+        mWriter.setLayerSourceCrop(
+                mPrimaryDisplay, layer,
+                {0, 0, static_cast<float>(mDisplayWidth), static_cast<float>(mDisplayHeight)});
+        mWriter.setLayerTransform(mPrimaryDisplay, layer, static_cast<Transform>(0));
+        mWriter.setLayerVisibleRegion(mPrimaryDisplay, layer,
+                                      std::vector<Rect>(1, {0, 0, mDisplayWidth, mDisplayHeight}));
+        mWriter.setLayerZOrder(mPrimaryDisplay, layer, 10);
+        mWriter.setLayerBlendMode(mPrimaryDisplay, layer, BlendMode::NONE);
+        mWriter.setLayerSurfaceDamage(mPrimaryDisplay, layer,
+                                      std::vector<Rect>(1, {0, 0, mDisplayWidth, mDisplayHeight}));
+        mWriter.setLayerDataspace(mPrimaryDisplay, layer, common::Dataspace::UNKNOWN);
+        return layer;
+    }
+
+    void Test_setActiveConfigWithConstraints(const TestParameters& params) {
+        for (VtsDisplay& display : mDisplays) {
+            forEachTwoConfigs(display.get(), [&](int32_t config1, int32_t config2) {
+                setActiveConfig(display, config1);
+                sendRefreshFrame(display, nullptr);
+
+                int32_t vsyncPeriod1;
+                EXPECT_TRUE(mComposerClient
+                                    ->getDisplayAttribute(display.get(), config1,
+                                                          DisplayAttribute::VSYNC_PERIOD,
+                                                          &vsyncPeriod1)
+                                    .isOk());
+                int32_t configGroup1;
+                EXPECT_TRUE(mComposerClient
+                                    ->getDisplayAttribute(display.get(), config1,
+                                                          DisplayAttribute::CONFIG_GROUP,
+                                                          &configGroup1)
+                                    .isOk());
+                int32_t vsyncPeriod2;
+                EXPECT_TRUE(mComposerClient
+                                    ->getDisplayAttribute(display.get(), config2,
+                                                          DisplayAttribute::VSYNC_PERIOD,
+                                                          &vsyncPeriod2)
+                                    .isOk());
+                int32_t configGroup2;
+                EXPECT_TRUE(mComposerClient
+                                    ->getDisplayAttribute(display.get(), config2,
+                                                          DisplayAttribute::CONFIG_GROUP,
+                                                          &configGroup2)
+                                    .isOk());
+
+                if (vsyncPeriod1 == vsyncPeriod2) {
+                    return;  // continue
+                }
+
+                // We don't allow delayed change when changing config groups
+                if (params.delayForChange > 0 && configGroup1 != configGroup2) {
+                    return;  // continue
+                }
+
+                VsyncPeriodChangeTimeline timeline;
+                VsyncPeriodChangeConstraints constraints = {
+                        .desiredTimeNanos = systemTime() + params.delayForChange,
+                        .seamlessRequired = false};
+                EXPECT_TRUE(setActiveConfigWithConstraints(display, config2, constraints, &timeline)
+                                    .isOk());
+
+                EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos >= constraints.desiredTimeNanos);
+                // Refresh rate should change within a reasonable time
+                constexpr std::chrono::nanoseconds kReasonableTimeForChange = 1s;  // 1 second
+                EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos - constraints.desiredTimeNanos <=
+                            kReasonableTimeForChange.count());
+
+                if (timeline.refreshRequired) {
+                    if (params.refreshMiss) {
+                        // Miss the refresh frame on purpose to make sure the implementation sends a
+                        // callback
+                        std::this_thread::sleep_until(toTimePoint(timeline.refreshTimeNanos) +
+                                                      100ms);
+                    }
+                    sendRefreshFrame(display, &timeline);
+                }
+                waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos,
+                                         vsyncPeriod1, vsyncPeriod2);
+
+                // At this point the refresh rate should have changed already, however in rare
+                // cases the implementation might have missed the deadline. In this case a new
+                // timeline should have been provided.
+                auto newTimeline = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
+                if (timeline.refreshRequired && params.refreshMiss) {
+                    EXPECT_TRUE(newTimeline.has_value());
+                }
+
+                if (newTimeline.has_value()) {
+                    if (newTimeline->refreshRequired) {
+                        sendRefreshFrame(display, &newTimeline.value());
+                    }
+                    waitForVsyncPeriodChange(display.get(), newTimeline.value(),
+                                             constraints.desiredTimeNanos, vsyncPeriod1,
+                                             vsyncPeriod2);
+                }
+
+                int32_t vsyncPeriodNanos;
+                EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
+                                    .isOk());
+                EXPECT_EQ(vsyncPeriodNanos, vsyncPeriod2);
+            });
+        }
+    }
+
+    void Test_expectedPresentTime(std::optional<int> framesDelay) {
+        ASSERT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON).isOk());
+
+        const auto vsyncPeriod = getVsyncPeriod();
+
+        const auto buffer1 = allocate();
+        const auto buffer2 = allocate();
+        ASSERT_NE(nullptr, buffer1);
+        ASSERT_NE(nullptr, buffer2);
+
+        const auto layer = createOnScreenLayer();
+        mWriter.setLayerBuffer(mPrimaryDisplay, layer, 0, buffer1->handle, -1);
+        const sp<::android::Fence> presentFence1 =
+                presentAndGetFence(ComposerClientWriter::kNoTimestamp);
+        presentFence1->waitForever(LOG_TAG);
+
+        auto expectedPresentTime = presentFence1->getSignalTime() + vsyncPeriod;
+        if (framesDelay.has_value()) {
+            expectedPresentTime += *framesDelay * vsyncPeriod;
+        }
+
+        mWriter.setLayerBuffer(mPrimaryDisplay, layer, 0, buffer2->handle, -1);
+        const auto setExpectedPresentTime = [&]() -> std::optional<ClockMonotonicTimestamp> {
+            if (!framesDelay.has_value()) {
+                return ComposerClientWriter::kNoTimestamp;
+            } else if (*framesDelay == 0) {
+                return ClockMonotonicTimestamp{0};
+            }
+            return ClockMonotonicTimestamp{expectedPresentTime};
+        }();
+
+        const sp<::android::Fence> presentFence2 = presentAndGetFence(setExpectedPresentTime);
+        presentFence2->waitForever(LOG_TAG);
+
+        const auto actualPresentTime = presentFence2->getSignalTime();
+        const auto presentError = std::abs(expectedPresentTime - actualPresentTime);
+        EXPECT_LE(presentError, vsyncPeriod / 2);
+
+        ASSERT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF).isOk());
+    }
+
+    // clang-format off
+    const std::array<float, 16> kIdentity = {{
+            1.0f, 0.0f, 0.0f, 0.0f,
+            0.0f, 1.0f, 0.0f, 0.0f,
+            0.0f, 0.0f, 1.0f, 0.0f,
+            0.0f, 0.0f, 0.0f, 1.0f,
+    }};
+    // clang-format on
+
+    ComposerClientWriter mWriter;
+    ComposerClientReader mReader;
+};
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_COLOR_TRANSFORM) {
+    mWriter.setColorTransform(mPrimaryDisplay, kIdentity.data());
+    execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SetLayerColorTransform) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+    mWriter.setLayerColorTransform(mPrimaryDisplay, layer, kIdentity.data());
+    execute();
+
+    const auto errors = mReader.takeErrors();
+    if (errors.size() == 1 && errors[0].errorCode == EX_UNSUPPORTED_OPERATION) {
+        GTEST_SUCCEED() << "setLayerColorTransform is not supported";
+        return;
+    }
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_CLIENT_TARGET) {
+    EXPECT_TRUE(
+            mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount).isOk());
+
+    mWriter.setClientTarget(mPrimaryDisplay, 0, nullptr, -1, Dataspace::UNKNOWN,
+                            std::vector<Rect>());
+
+    execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_OUTPUT_BUFFER) {
+    int32_t virtualDisplayCount;
+    EXPECT_TRUE(mComposerClient->getMaxVirtualDisplayCount(&virtualDisplayCount).isOk());
+    if (virtualDisplayCount == 0) {
+        GTEST_SUCCEED() << "no virtual display support";
+        return;
+    }
+
+    VirtualDisplay display;
+    EXPECT_TRUE(mComposerClient
+                        ->createVirtualDisplay(64, 64, common::PixelFormat::IMPLEMENTATION_DEFINED,
+                                               kBufferSlotCount, &display)
+                        .isOk());
+
+    const auto buffer = allocate();
+    const auto handle = buffer->handle;
+    mWriter.setOutputBuffer(display.display, 0, handle, -1);
+    execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, VALIDATE_DISPLAY) {
+    mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+    execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, ACCEPT_DISPLAY_CHANGES) {
+    mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+    mWriter.acceptDisplayChanges(mPrimaryDisplay);
+    execute();
+}
+
+// TODO(b/208441745) fix the test failure
+TEST_P(GraphicsComposerAidlCommandTest, PRESENT_DISPLAY) {
+    mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+    mWriter.presentDisplay(mPrimaryDisplay);
+    execute();
+}
+
+/**
+ * Test IComposerClient::Command::PRESENT_DISPLAY
+ *
+ * Test that IComposerClient::Command::PRESENT_DISPLAY works without
+ * additional call to validateDisplay when only the layer buffer handle and
+ * surface damage have been set
+ */
+// TODO(b/208441745) fix the test failure
+TEST_P(GraphicsComposerAidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) {
+    std::vector<Capability> capabilities;
+    EXPECT_TRUE(mComposer->getCapabilities(&capabilities).isOk());
+    if (none_of(capabilities.begin(), capabilities.end(),
+                [&](auto item) { return item == Capability::SKIP_VALIDATE; })) {
+        GTEST_SUCCEED() << "Device does not have skip validate capability, skipping";
+        return;
+    }
+    mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON);
+
+    std::vector<RenderIntent> renderIntents;
+    mComposerClient->getRenderIntents(mPrimaryDisplay, ColorMode::NATIVE, &renderIntents);
+    for (auto intent : renderIntents) {
+        mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE, intent);
+
+        const auto buffer = allocate();
+        const auto handle = buffer->handle;
+        ASSERT_NE(nullptr, handle);
+
+        Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
+
+        int64_t layer;
+        EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+        mWriter.setLayerCompositionType(mPrimaryDisplay, layer, Composition::DEVICE);
+        mWriter.setLayerDisplayFrame(mPrimaryDisplay, layer, displayFrame);
+        mWriter.setLayerPlaneAlpha(mPrimaryDisplay, layer, 1);
+        mWriter.setLayerSourceCrop(mPrimaryDisplay, layer,
+                                   {0, 0, (float)mDisplayWidth, (float)mDisplayHeight});
+        mWriter.setLayerTransform(mPrimaryDisplay, layer, static_cast<Transform>(0));
+        mWriter.setLayerVisibleRegion(mPrimaryDisplay, layer, std::vector<Rect>(1, displayFrame));
+        mWriter.setLayerZOrder(mPrimaryDisplay, layer, 10);
+        mWriter.setLayerBlendMode(mPrimaryDisplay, layer, BlendMode::NONE);
+        mWriter.setLayerSurfaceDamage(mPrimaryDisplay, layer, std::vector<Rect>(1, displayFrame));
+        mWriter.setLayerBuffer(mPrimaryDisplay, layer, 0, handle, -1);
+        mWriter.setLayerDataspace(mPrimaryDisplay, layer, Dataspace::UNKNOWN);
+
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED() << "Composition change requested, skipping test";
+            return;
+        }
+
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        const auto buffer2 = allocate();
+        const auto handle2 = buffer2->handle;
+        ASSERT_NE(nullptr, handle2);
+        mWriter.setLayerBuffer(mPrimaryDisplay, layer, 0, handle2, -1);
+        mWriter.setLayerSurfaceDamage(mPrimaryDisplay, layer, std::vector<Rect>(1, {0, 0, 10, 10}));
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+    }
+}
+
+// TODO(b/208441745) fix the test failure
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_CURSOR_POSITION) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    const auto buffer = allocate();
+    const auto handle = buffer->handle;
+    ASSERT_NE(nullptr, handle);
+    Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
+
+    mWriter.setLayerBuffer(mPrimaryDisplay, layer, 0, handle, -1);
+    mWriter.setLayerCompositionType(mPrimaryDisplay, layer, Composition::CURSOR);
+    mWriter.setLayerDisplayFrame(mPrimaryDisplay, layer, displayFrame);
+    mWriter.setLayerPlaneAlpha(mPrimaryDisplay, layer, 1);
+    mWriter.setLayerSourceCrop(mPrimaryDisplay, layer,
+                               {0, 0, (float)mDisplayWidth, (float)mDisplayHeight});
+    mWriter.setLayerTransform(mPrimaryDisplay, layer, static_cast<Transform>(0));
+    mWriter.setLayerVisibleRegion(mPrimaryDisplay, layer, std::vector<Rect>(1, displayFrame));
+    mWriter.setLayerZOrder(mPrimaryDisplay, layer, 10);
+    mWriter.setLayerBlendMode(mPrimaryDisplay, layer, BlendMode::NONE);
+    mWriter.setLayerSurfaceDamage(mPrimaryDisplay, layer, std::vector<Rect>(1, displayFrame));
+    mWriter.setLayerDataspace(mPrimaryDisplay, layer, Dataspace::UNKNOWN);
+    mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+
+    execute();
+
+    if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+        GTEST_SUCCEED() << "Composition change requested, skipping test";
+        return;
+    }
+    mWriter.presentDisplay(mPrimaryDisplay);
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerCursorPosition(mPrimaryDisplay, layer, 1, 1);
+    execute();
+
+    mWriter.setLayerCursorPosition(mPrimaryDisplay, layer, 0, 0);
+    mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+    mWriter.presentDisplay(mPrimaryDisplay);
+    execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_BUFFER) {
+    const auto buffer = allocate();
+    const auto handle = buffer->handle;
+    ASSERT_NE(nullptr, handle);
+
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+    mWriter.setLayerBuffer(mPrimaryDisplay, layer, 0, handle, -1);
+    execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_SURFACE_DAMAGE) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    Rect empty{0, 0, 0, 0};
+    Rect unit{0, 0, 1, 1};
+
+    mWriter.setLayerSurfaceDamage(mPrimaryDisplay, layer, std::vector<Rect>(1, empty));
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerSurfaceDamage(mPrimaryDisplay, layer, std::vector<Rect>(1, unit));
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerSurfaceDamage(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());
+
+    mWriter.setLayerBlendMode(mPrimaryDisplay, layer, BlendMode::NONE);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerBlendMode(mPrimaryDisplay, layer, BlendMode::PREMULTIPLIED);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerBlendMode(mPrimaryDisplay, layer, BlendMode::COVERAGE);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_COLOR) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    mWriter.setLayerColor(mPrimaryDisplay, layer,
+                          Color{static_cast<int8_t>(0xff), static_cast<int8_t>(0xff),
+                                static_cast<int8_t>(0xff), static_cast<int8_t>(0xff)});
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerColor(mPrimaryDisplay, layer, Color{0, 0, 0, 0});
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_COMPOSITION_TYPE) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    mWriter.setLayerCompositionType(mPrimaryDisplay, layer, Composition::CLIENT);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerCompositionType(mPrimaryDisplay, layer, Composition::DEVICE);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerCompositionType(mPrimaryDisplay, layer, Composition::SOLID_COLOR);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerCompositionType(mPrimaryDisplay, layer, Composition::CURSOR);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_DATASPACE) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    mWriter.setLayerDataspace(mPrimaryDisplay, layer, Dataspace::UNKNOWN);
+    execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_DISPLAY_FRAME) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    mWriter.setLayerDisplayFrame(mPrimaryDisplay, layer, Rect{0, 0, 1, 1});
+    execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_PLANE_ALPHA) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    mWriter.setLayerPlaneAlpha(mPrimaryDisplay, layer, 0.0f);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerPlaneAlpha(mPrimaryDisplay, layer, 1.0f);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_SIDEBAND_STREAM) {
+    std::vector<Capability> capabilities;
+    EXPECT_TRUE(mComposer->getCapabilities(&capabilities).isOk());
+    if (none_of(capabilities.begin(), capabilities.end(),
+                [&](auto& item) { return item == Capability::SIDEBAND_STREAM; })) {
+        GTEST_SUCCEED() << "no sideband stream support";
+        return;
+    }
+
+    const auto buffer = allocate();
+    const auto handle = buffer->handle;
+    ASSERT_NE(nullptr, handle);
+
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    mWriter.setLayerSidebandStream(mPrimaryDisplay, layer, handle);
+    execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_SOURCE_CROP) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    mWriter.setLayerSourceCrop(mPrimaryDisplay, layer, FRect{0.0f, 0.0f, 1.0f, 1.0f});
+    execute();
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_TRANSFORM) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    mWriter.setLayerTransform(mPrimaryDisplay, layer, static_cast<Transform>(0));
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerTransform(mPrimaryDisplay, layer, Transform::FLIP_H);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerTransform(mPrimaryDisplay, layer, Transform::FLIP_V);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerTransform(mPrimaryDisplay, layer, Transform::ROT_90);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerTransform(mPrimaryDisplay, layer, Transform::ROT_180);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerTransform(mPrimaryDisplay, layer, Transform::ROT_270);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerTransform(mPrimaryDisplay, layer,
+                              static_cast<Transform>(static_cast<int>(Transform::FLIP_H) |
+                                                     static_cast<int>(Transform::ROT_90)));
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerTransform(mPrimaryDisplay, layer,
+                              static_cast<Transform>(static_cast<int>(Transform::FLIP_V) |
+                                                     static_cast<int>(Transform::ROT_90)));
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_VISIBLE_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.setLayerVisibleRegion(mPrimaryDisplay, layer, std::vector<Rect>(1, empty));
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerVisibleRegion(mPrimaryDisplay, layer, std::vector<Rect>(1, unit));
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerVisibleRegion(mPrimaryDisplay, layer, std::vector<Rect>());
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_Z_ORDER) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    mWriter.setLayerZOrder(mPrimaryDisplay, layer, 10);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    mWriter.setLayerZOrder(mPrimaryDisplay, layer, 0);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_PER_FRAME_METADATA) {
+    int64_t layer;
+    EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
+
+    /**
+     * DISPLAY_P3 is a color space that uses the DCI_P3 primaries,
+     * the D65 white point and the SRGB transfer functions.
+     * Rendering Intent: Colorimetric
+     * Primaries:
+     *                  x       y
+     *  green           0.265   0.690
+     *  blue            0.150   0.060
+     *  red             0.680   0.320
+     *  white (D65)     0.3127  0.3290
+     */
+
+    std::vector<PerFrameMetadata> aidlMetadata;
+    aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X, 0.680f});
+    aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y, 0.320f});
+    aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X, 0.265f});
+    aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y, 0.690f});
+    aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X, 0.150f});
+    aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y, 0.060f});
+    aidlMetadata.push_back({PerFrameMetadataKey::WHITE_POINT_X, 0.3127f});
+    aidlMetadata.push_back({PerFrameMetadataKey::WHITE_POINT_Y, 0.3290f});
+    aidlMetadata.push_back({PerFrameMetadataKey::MAX_LUMINANCE, 100.0f});
+    aidlMetadata.push_back({PerFrameMetadataKey::MIN_LUMINANCE, 0.1f});
+    aidlMetadata.push_back({PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, 78.0});
+    aidlMetadata.push_back({PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, 62.0});
+    mWriter.setLayerPerFrameMetadata(mPrimaryDisplay, layer, aidlMetadata);
+    execute();
+
+    const auto errors = mReader.takeErrors();
+    if (errors.size() == 1 && errors[0].errorCode == EX_UNSUPPORTED_OPERATION) {
+        GTEST_SUCCEED() << "SetLayerPerFrameMetadata is not supported";
+        EXPECT_TRUE(mComposerClient->destroyLayer(mPrimaryDisplay, layer).isOk());
+        return;
+    }
+
+    EXPECT_TRUE(mComposerClient->destroyLayer(mPrimaryDisplay, layer).isOk());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, setActiveConfigWithConstraints) {
+    Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = false});
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, setActiveConfigWithConstraints_Delayed) {
+    Test_setActiveConfigWithConstraints({.delayForChange = 300'000'000,  // 300ms
+                                         .refreshMiss = false});
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, setActiveConfigWithConstraints_MissRefresh) {
+    Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = true});
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, getDisplayVsyncPeriod) {
+    for (VtsDisplay& display : mDisplays) {
+        std::vector<int32_t> configs;
+        EXPECT_TRUE(mComposerClient->getDisplayConfigs(display.get(), &configs).isOk());
+        for (int32_t config : configs) {
+            int32_t expectedVsyncPeriodNanos = -1;
+            EXPECT_TRUE(mComposerClient
+                                ->getDisplayAttribute(display.get(), config,
+                                                      DisplayAttribute::VSYNC_PERIOD,
+                                                      &expectedVsyncPeriodNanos)
+                                .isOk());
+
+            VsyncPeriodChangeTimeline timeline;
+            VsyncPeriodChangeConstraints constraints;
+
+            constraints.desiredTimeNanos = systemTime();
+            constraints.seamlessRequired = false;
+            EXPECT_TRUE(mComposerClient
+                                ->setActiveConfigWithConstraints(display.get(), config, constraints,
+                                                                 &timeline)
+                                .isOk());
+
+            if (timeline.refreshRequired) {
+                sendRefreshFrame(display, &timeline);
+            }
+            waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos, 0,
+                                     expectedVsyncPeriodNanos);
+
+            int32_t vsyncPeriodNanos;
+            int retryCount = 100;
+            do {
+                std::this_thread::sleep_for(10ms);
+                vsyncPeriodNanos = 0;
+                EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
+                                    .isOk());
+                --retryCount;
+            } while (vsyncPeriodNanos != expectedVsyncPeriodNanos && retryCount > 0);
+
+            EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
+
+            // Make sure that the vsync period stays the same if the active config is not
+            // changed.
+            auto timeout = 1ms;
+            for (int i = 0; i < 10; i++) {
+                std::this_thread::sleep_for(timeout);
+                timeout *= 2;
+                vsyncPeriodNanos = 0;
+                EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
+                                    .isOk());
+                EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
+            }
+        }
+    }
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, setActiveConfigWithConstraints_SeamlessNotAllowed) {
+    VsyncPeriodChangeTimeline timeline;
+    VsyncPeriodChangeConstraints constraints;
+
+    constraints.seamlessRequired = true;
+    constraints.desiredTimeNanos = systemTime();
+
+    for (VtsDisplay& display : mDisplays) {
+        forEachTwoConfigs(display.get(), [&](int32_t config1, int32_t config2) {
+            int32_t configGroup1;
+            EXPECT_TRUE(mComposerClient
+                                ->getDisplayAttribute(display.get(), config1,
+                                                      DisplayAttribute::CONFIG_GROUP, &configGroup1)
+                                .isOk());
+            int32_t configGroup2;
+            EXPECT_TRUE(mComposerClient
+                                ->getDisplayAttribute(display.get(), config2,
+                                                      DisplayAttribute::CONFIG_GROUP, &configGroup2)
+                                .isOk());
+            if (configGroup1 != configGroup2) {
+                setActiveConfig(display, config1);
+                sendRefreshFrame(display, nullptr);
+                EXPECT_EQ(IComposerClient::EX_SEAMLESS_NOT_ALLOWED,
+                          setActiveConfigWithConstraints(display, config2, constraints, &timeline)
+                                  .getServiceSpecificError());
+            }
+        });
+    }
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, expectedPresentTime_NoTimestamp) {
+    ASSERT_NO_FATAL_FAILURE(Test_expectedPresentTime(std::nullopt));
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, expectedPresentTime_0) {
+    ASSERT_NO_FATAL_FAILURE(Test_expectedPresentTime(0));
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, expectedPresentTime_5) {
+    ASSERT_NO_FATAL_FAILURE(Test_expectedPresentTime(5));
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsComposerAidlCommandTest,
+        testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
+        ::android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsComposerAidlTest,
+        testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
+        ::android::PrintInstanceNameToString);
+}  // namespace
+}  // namespace aidl::android::hardware::graphics::composer3::vts
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    using namespace std::chrono_literals;
+    if (!android::base::WaitForProperty("init.svc.surfaceflinger", "stopped", 10s)) {
+        ALOGE("Failed to stop init.svc.surfaceflinger");
+        return -1;
+    }
+
+    android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
+
+    // The binder threadpool we start will inherit sched policy and priority
+    // of (this) creating thread. We want the binder thread pool to have
+    // SCHED_FIFO policy and priority 1 (lowest RT priority)
+    // Once the pool is created we reset this thread's priority back to
+    // original.
+    // This thread policy is based on what we do in the SurfaceFlinger while starting
+    // the thread pool and we need to replicate that for the VTS tests.
+    int newPriority = 0;
+    int origPolicy = sched_getscheduler(0);
+    struct sched_param origSchedParam;
+
+    int errorInPriorityModification = sched_getparam(0, &origSchedParam);
+    if (errorInPriorityModification == 0) {
+        int policy = SCHED_FIFO;
+        newPriority = sched_get_priority_min(policy);
+
+        struct sched_param param;
+        param.sched_priority = newPriority;
+
+        errorInPriorityModification = sched_setscheduler(0, policy, &param);
+    }
+
+    // start the thread pool
+    android::ProcessState::self()->startThreadPool();
+
+    // Reset current thread's policy and priority
+    if (errorInPriorityModification == 0) {
+        errorInPriorityModification = sched_setscheduler(0, origPolicy, &origSchedParam);
+    } else {
+        ALOGE("Failed to set VtsHalGraphicsComposer3_TargetTest binder threadpool priority to "
+              "SCHED_FIFO");
+    }
+
+    return RUN_ALL_TESTS();
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/Android.bp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/Android.bp
new file mode 100644
index 0000000..df038db
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/Android.bp
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+    name: "android.hardware.graphics.composer@3-vts",
+    defaults: ["hidl_defaults"],
+    srcs: [
+        "GraphicsComposerCallback.cpp",
+        "ReadbackVts.cpp",
+        "RenderEngineVts.cpp",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer3-command-buffer",
+    ],
+    static_libs: [
+        "android.hardware.graphics.composer3-V1-ndk",
+        "android.hardware.graphics.common-V3-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+        "libarect",
+        "libgtest",
+        "libbase",
+        "libfmq",
+        "libsync",
+        "libmath",
+        "libaidlcommonsupport",
+        "libnativewindow",
+        "librenderengine",
+        "libshaders",
+        "libtonemap",
+        "android.hardware.graphics.mapper@2.0-vts",
+        "android.hardware.graphics.mapper@2.1-vts",
+        "android.hardware.graphics.mapper@3.0-vts",
+        "android.hardware.graphics.mapper@4.0-vts",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libhidlbase",
+        "libui",
+        "android.hardware.graphics.composer3-V1-ndk",
+    ],
+    export_static_lib_headers: [
+        "android.hardware.graphics.mapper@2.1-vts",
+        "librenderengine",
+    ],
+    cflags: [
+        "-O0",
+        "-g",
+        "-DLOG_TAG=\"ComposerVts\"",
+        "-Wconversion",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer3-command-buffer",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/GraphicsComposerCallback.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/GraphicsComposerCallback.cpp
new file mode 100644
index 0000000..307fe15
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/GraphicsComposerCallback.cpp
@@ -0,0 +1,128 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "include/GraphicsComposerCallback.h"
+#include <log/log_main.h>
+
+#pragma push_macro("LOG_TAG")
+#undef LOG_TAG
+#define LOG_TAG "GraphicsComposerCallback"
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+
+void GraphicsComposerCallback::setVsyncAllowed(bool allowed) {
+    std::scoped_lock lock(mMutex);
+    mVsyncAllowed = allowed;
+}
+
+std::vector<int64_t> GraphicsComposerCallback::getDisplays() const {
+    std::scoped_lock lock(mMutex);
+    return std::vector<int64_t>(mDisplays.begin(), mDisplays.end());
+}
+
+int32_t GraphicsComposerCallback::getInvalidHotplugCount() const {
+    std::scoped_lock lock(mMutex);
+    return mInvalidHotplugCount;
+}
+
+int32_t GraphicsComposerCallback::getInvalidRefreshCount() const {
+    std::scoped_lock lock(mMutex);
+    return mInvalidRefreshCount;
+}
+
+int32_t GraphicsComposerCallback::getInvalidVsyncCount() const {
+    std::scoped_lock lock(mMutex);
+    return mInvalidVsyncCount;
+}
+
+int32_t GraphicsComposerCallback::getInvalidVsyncPeriodChangeCount() const {
+    std::scoped_lock lock(mMutex);
+    return mInvalidVsyncPeriodChangeCount;
+}
+
+int32_t GraphicsComposerCallback::getInvalidSeamlessPossibleCount() const {
+    std::scoped_lock lock(mMutex);
+    return mInvalidSeamlessPossibleCount;
+}
+
+std::optional<VsyncPeriodChangeTimeline>
+GraphicsComposerCallback::takeLastVsyncPeriodChangeTimeline() {
+    std::scoped_lock lock(mMutex);
+
+    std::optional<VsyncPeriodChangeTimeline> ret;
+    ret.swap(mTimeline);
+
+    return ret;
+}
+
+::ndk::ScopedAStatus GraphicsComposerCallback::onHotplug(int64_t in_display, bool in_connected) {
+    std::scoped_lock lock(mMutex);
+    if (in_connected) {
+        if (!mDisplays.insert(in_display).second) {
+            mInvalidHotplugCount++;
+        }
+    } else {
+        if (!mDisplays.erase(in_display)) {
+            mInvalidHotplugCount++;
+        }
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus GraphicsComposerCallback::onRefresh(int64_t display) {
+    std::scoped_lock lock(mMutex);
+
+    if (mDisplays.count(display) == 0) {
+        mInvalidRefreshCount++;
+    }
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus GraphicsComposerCallback::onVsync(int64_t in_display, int64_t in_timestamp,
+                                                       int32_t in_vsyncPeriodNanos) {
+    std::scoped_lock lock(mMutex);
+    if (!mVsyncAllowed || mDisplays.count(in_display) == 0) {
+        mInvalidVsyncCount++;
+    }
+
+    ALOGV("%ld, %d", static_cast<long>(in_timestamp), in_vsyncPeriodNanos);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus GraphicsComposerCallback::onVsyncPeriodTimingChanged(
+        int64_t in_display,
+        const ::aidl::android::hardware::graphics::composer3::VsyncPeriodChangeTimeline&
+                in_updatedTimeline) {
+    std::scoped_lock lock(mMutex);
+    if (mDisplays.count(in_display) == 0) {
+        mInvalidVsyncPeriodChangeCount++;
+    }
+    mTimeline = in_updatedTimeline;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus GraphicsComposerCallback::onSeamlessPossible(int64_t in_display) {
+    std::scoped_lock lock(mMutex);
+    if (mDisplays.count(in_display)) {
+        mInvalidSeamlessPossibleCount++;
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::graphics::composer3::vts
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
new file mode 100644
index 0000000..5eb912b
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
@@ -0,0 +1,356 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include "include/ReadbackVts.h"
+#include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include "include/RenderEngineVts.h"
+#include "renderengine/ExternalTexture.h"
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop  // ignored "-Wconversion
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+
+const std::vector<ColorMode> ReadbackHelper::colorModes = {ColorMode::SRGB, ColorMode::DISPLAY_P3};
+const std::vector<Dataspace> ReadbackHelper::dataspaces = {common::Dataspace::SRGB,
+                                                           common::Dataspace::DISPLAY_P3};
+
+void TestLayer::write(ComposerClientWriter& writer) {
+    writer.setLayerDisplayFrame(mDisplay, mLayer, mDisplayFrame);
+    writer.setLayerSourceCrop(mDisplay, mLayer, mSourceCrop);
+    writer.setLayerZOrder(mDisplay, mLayer, mZOrder);
+    writer.setLayerSurfaceDamage(mDisplay, mLayer, mSurfaceDamage);
+    writer.setLayerTransform(mDisplay, mLayer, mTransform);
+    writer.setLayerPlaneAlpha(mDisplay, mLayer, mAlpha);
+    writer.setLayerBlendMode(mDisplay, mLayer, mBlendMode);
+}
+
+std::string ReadbackHelper::getColorModeString(ColorMode mode) {
+    switch (mode) {
+        case ColorMode::SRGB:
+            return {"SRGB"};
+        case ColorMode::DISPLAY_P3:
+            return {"DISPLAY_P3"};
+        default:
+            return {"Unsupported color mode for readback"};
+    }
+}
+
+std::string ReadbackHelper::getDataspaceString(common::Dataspace dataspace) {
+    switch (dataspace) {
+        case common::Dataspace::SRGB:
+            return {"SRGB"};
+        case common::Dataspace::DISPLAY_P3:
+            return {"DISPLAY_P3"};
+        case common::Dataspace::UNKNOWN:
+            return {"UNKNOWN"};
+        default:
+            return {"Unsupported dataspace for readback"};
+    }
+}
+
+Dataspace ReadbackHelper::getDataspaceForColorMode(ColorMode mode) {
+    switch (mode) {
+        case ColorMode::DISPLAY_P3:
+            return Dataspace::DISPLAY_P3;
+        case ColorMode::SRGB:
+        default:
+            return common::Dataspace::UNKNOWN;
+    }
+}
+
+LayerSettings TestLayer::toRenderEngineLayerSettings() {
+    LayerSettings layerSettings;
+
+    layerSettings.alpha = ::android::half(mAlpha);
+    layerSettings.disableBlending = mBlendMode == BlendMode::NONE;
+    layerSettings.geometry.boundaries = ::android::FloatRect(
+            static_cast<float>(mDisplayFrame.left), static_cast<float>(mDisplayFrame.top),
+            static_cast<float>(mDisplayFrame.right), static_cast<float>(mDisplayFrame.bottom));
+
+    const ::android::mat4 translation = ::android::mat4::translate(::android::vec4(
+            (static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_H)
+                     ? static_cast<float>(-mDisplayFrame.right)
+                     : 0.0f),
+            (static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_V)
+                     ? static_cast<float>(-mDisplayFrame.bottom)
+                     : 0.0f),
+            0.0f, 1.0f));
+
+    const ::android::mat4 scale = ::android::mat4::scale(::android::vec4(
+            static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_H) ? -1.0f
+                                                                                         : 1.0f,
+            static_cast<uint64_t>(mTransform) & static_cast<uint64_t>(Transform::FLIP_V) ? -1.0f
+                                                                                         : 1.0f,
+            1.0f, 1.0f));
+
+    layerSettings.geometry.positionTransform = scale * translation;
+
+    return layerSettings;
+}
+
+int32_t ReadbackHelper::GetBytesPerPixel(common::PixelFormat pixelFormat) {
+    switch (pixelFormat) {
+        case common::PixelFormat::RGBA_8888:
+            return 4;
+        case common::PixelFormat::RGB_888:
+            return 3;
+        default:
+            return -1;
+    }
+}
+
+void ReadbackHelper::fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData,
+                                common::PixelFormat pixelFormat,
+                                std::vector<Color> desiredPixelColors) {
+    ASSERT_TRUE(pixelFormat == common::PixelFormat::RGB_888 ||
+                pixelFormat == common::PixelFormat::RGBA_8888);
+    int32_t bytesPerPixel = GetBytesPerPixel(pixelFormat);
+    ASSERT_NE(-1, bytesPerPixel);
+    for (int row = 0; row < height; row++) {
+        for (int col = 0; col < width; col++) {
+            auto pixel = row * static_cast<int32_t>(width) + col;
+            Color srcColor = desiredPixelColors[static_cast<size_t>(pixel)];
+
+            int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
+            uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+            pixelColor[0] = static_cast<uint8_t>(srcColor.r);
+            pixelColor[1] = static_cast<uint8_t>(srcColor.g);
+            pixelColor[2] = static_cast<uint8_t>(srcColor.b);
+
+            if (bytesPerPixel == 4) {
+                pixelColor[3] = static_cast<uint8_t>(srcColor.a);
+            }
+        }
+    }
+}
+
+void ReadbackHelper::clearColors(std::vector<Color>& expectedColors, int32_t width, int32_t height,
+                                 int32_t displayWidth) {
+    for (int row = 0; row < height; row++) {
+        for (int col = 0; col < width; col++) {
+            int pixel = row * displayWidth + col;
+            expectedColors[static_cast<size_t>(pixel)] = BLACK;
+        }
+    }
+}
+
+void ReadbackHelper::fillColorsArea(std::vector<Color>& expectedColors, int32_t stride, Rect area,
+                                    Color color) {
+    for (int row = area.top; row < area.bottom; row++) {
+        for (int col = area.left; col < area.right; col++) {
+            int pixel = row * stride + col;
+            expectedColors[static_cast<size_t>(pixel)] = color;
+        }
+    }
+}
+
+bool ReadbackHelper::readbackSupported(const common::PixelFormat& pixelFormat,
+                                       const common::Dataspace& dataspace) {
+    if (pixelFormat != common::PixelFormat::RGB_888 &&
+        pixelFormat != common::PixelFormat::RGBA_8888) {
+        return false;
+    }
+    if (std::find(dataspaces.begin(), dataspaces.end(), dataspace) == dataspaces.end()) {
+        return false;
+    }
+    return true;
+}
+
+void ReadbackHelper::compareColorBuffers(std::vector<Color>& expectedColors, void* bufferData,
+                                         const int32_t stride, const uint32_t width,
+                                         const uint32_t height, common::PixelFormat pixelFormat) {
+    const int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat);
+    ASSERT_NE(-1, bytesPerPixel);
+    for (int row = 0; row < height; row++) {
+        for (int col = 0; col < width; col++) {
+            auto pixel = row * static_cast<int32_t>(width) + col;
+            int offset = (row * stride + col) * bytesPerPixel;
+            uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+
+            ASSERT_EQ(static_cast<int8_t>(expectedColors[static_cast<size_t>(pixel)].r),
+                      pixelColor[0]);
+            ASSERT_EQ(static_cast<int8_t>(expectedColors[static_cast<size_t>(pixel)].g),
+                      pixelColor[1]);
+            ASSERT_EQ(static_cast<int8_t>(expectedColors[static_cast<size_t>(pixel)].b),
+                      pixelColor[2]);
+        }
+    }
+}
+
+ReadbackBuffer::ReadbackBuffer(int64_t display, const std::shared_ptr<IComposerClient>& client,
+                               const ::android::sp<::android::GraphicBuffer>& graphicBuffer,
+                               int32_t width, int32_t height, common::PixelFormat pixelFormat,
+                               common::Dataspace dataspace) {
+    mDisplay = display;
+
+    mComposerClient = client;
+    mGraphicBuffer = graphicBuffer;
+
+    mPixelFormat = pixelFormat;
+    mDataspace = dataspace;
+
+    mWidth = static_cast<uint32_t>(width);
+    mHeight = static_cast<uint32_t>(height);
+    mLayerCount = 1;
+    mUsage = static_cast<uint64_t>(static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+                                   static_cast<uint64_t>(common::BufferUsage::GPU_TEXTURE));
+
+    mAccessRegion.top = 0;
+    mAccessRegion.left = 0;
+    mAccessRegion.right = static_cast<int32_t>(width);
+    mAccessRegion.bottom = static_cast<int32_t>(height);
+}
+
+::android::sp<::android::GraphicBuffer> ReadbackBuffer::allocate() {
+    return ::android::sp<::android::GraphicBuffer>::make(
+            mWidth, mHeight, static_cast<::android::PixelFormat>(mPixelFormat), mLayerCount, mUsage,
+            "ReadbackVts");
+}
+
+void ReadbackBuffer::setReadbackBuffer() {
+    mGraphicBuffer = allocate();
+    ASSERT_NE(nullptr, mGraphicBuffer);
+    ASSERT_EQ(::android::OK, mGraphicBuffer->initCheck());
+    aidl::android::hardware::common::NativeHandle bufferHandle =
+            ::android::dupToAidl(mGraphicBuffer->handle);
+    ::ndk::ScopedFileDescriptor fence = ::ndk::ScopedFileDescriptor(-1);
+    EXPECT_TRUE(mComposerClient->setReadbackBuffer(mDisplay, bufferHandle, fence).isOk());
+}
+
+void ReadbackBuffer::checkReadbackBuffer(std::vector<Color> expectedColors) {
+    // lock buffer for reading
+    ndk::ScopedFileDescriptor fenceHandle;
+    EXPECT_TRUE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle).isOk());
+
+    int outBytesPerPixel;
+    int outBytesPerStride;
+    void* bufData = nullptr;
+    auto status = mGraphicBuffer->lockAsync(mUsage, mAccessRegion, &bufData, fenceHandle.get(),
+                                            &outBytesPerPixel, &outBytesPerStride);
+    EXPECT_EQ(::android::OK, status);
+    ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
+    ReadbackHelper::compareColorBuffers(expectedColors, bufData, static_cast<int32_t>(mStride),
+                                        mWidth, mHeight, mPixelFormat);
+    status = mGraphicBuffer->unlock();
+    EXPECT_EQ(::android::OK, status);
+}
+
+void TestColorLayer::write(ComposerClientWriter& writer) {
+    TestLayer::write(writer);
+    writer.setLayerCompositionType(mDisplay, mLayer, Composition::SOLID_COLOR);
+    writer.setLayerColor(mDisplay, mLayer, mColor);
+}
+
+LayerSettings TestColorLayer::toRenderEngineLayerSettings() {
+    LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
+
+    layerSettings.source.solidColor =
+            ::android::half3(static_cast<::android::half>(mColor.r) / 255.0,
+                             static_cast<::android::half>(mColor.g) / 255.0,
+                             static_cast<::android::half>(mColor.b) / 255.0);
+    layerSettings.alpha =
+            mAlpha * static_cast<float>((static_cast<::android::half>(mColor.a) / 255.0));
+    return layerSettings;
+}
+
+TestBufferLayer::TestBufferLayer(const std::shared_ptr<IComposerClient>& client,
+                                 const ::android::sp<::android::GraphicBuffer>& graphicBuffer,
+                                 TestRenderEngine& renderEngine, int64_t display, uint32_t width,
+                                 uint32_t height, common::PixelFormat format,
+                                 Composition composition)
+    : TestLayer{client, display}, mRenderEngine(renderEngine) {
+    mGraphicBuffer = graphicBuffer;
+    mComposition = composition;
+    mWidth = width;
+    mHeight = height;
+    mLayerCount = 1;
+    mPixelFormat = format;
+    mUsage = (static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+              static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
+              static_cast<uint64_t>(common::BufferUsage::COMPOSER_OVERLAY) |
+              static_cast<uint64_t>(common::BufferUsage::GPU_TEXTURE));
+
+    mAccessRegion.top = 0;
+    mAccessRegion.left = 0;
+    mAccessRegion.right = static_cast<int32_t>(width);
+    mAccessRegion.bottom = static_cast<int32_t>(height);
+
+    setSourceCrop({0, 0, (float)width, (float)height});
+}
+
+void TestBufferLayer::write(ComposerClientWriter& writer) {
+    TestLayer::write(writer);
+    writer.setLayerCompositionType(mDisplay, mLayer, mComposition);
+    writer.setLayerVisibleRegion(mDisplay, mLayer, std::vector<Rect>(1, mDisplayFrame));
+    if (mGraphicBuffer->handle != nullptr)
+        writer.setLayerBuffer(mDisplay, mLayer, 0, mGraphicBuffer->handle, mFillFence);
+}
+
+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.usePremultipliedAlpha = mBlendMode == BlendMode::PREMULTIPLIED;
+
+    const float scaleX = (mSourceCrop.right - mSourceCrop.left) / (static_cast<float>(mWidth));
+    const float scaleY = (mSourceCrop.bottom - mSourceCrop.top) / (static_cast<float>(mHeight));
+    const float translateX = mSourceCrop.left / (static_cast<float>(mWidth));
+    const float translateY = mSourceCrop.top / (static_cast<float>(mHeight));
+
+    layerSettings.source.buffer.textureTransform =
+            ::android::mat4::translate(::android::vec4(translateX, translateY, 0, 1)) *
+            ::android::mat4::scale(::android::vec4(scaleX, scaleY, 1.0, 1.0));
+
+    return layerSettings;
+}
+
+void TestBufferLayer::fillBuffer(std::vector<Color>& expectedColors) {
+    void* bufData;
+    auto status = mGraphicBuffer->lock(mUsage, &bufData);
+    EXPECT_EQ(::android::OK, status);
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mWidth, mHeight, mStride, bufData,
+                                                       mPixelFormat, expectedColors));
+    EXPECT_EQ(::android::OK, mGraphicBuffer->unlock());
+}
+
+void TestBufferLayer::setBuffer(std::vector<Color> colors) {
+    mGraphicBuffer->reallocate(mWidth, mHeight, static_cast<::android::PixelFormat>(mPixelFormat),
+                               mLayerCount, mUsage);
+    ASSERT_NE(nullptr, mGraphicBuffer);
+    ASSERT_NE(nullptr, mGraphicBuffer->handle);
+    ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
+    ASSERT_EQ(::android::OK, mGraphicBuffer->initCheck());
+}
+
+void TestBufferLayer::setDataspace(common::Dataspace dataspace, ComposerClientWriter& writer) {
+    writer.setLayerDataspace(mDisplay, mLayer, dataspace);
+}
+
+void TestBufferLayer::setToClientComposition(ComposerClientWriter& writer) {
+    writer.setLayerCompositionType(mDisplay, mLayer, Composition::CLIENT);
+}
+
+}  // namespace aidl::android::hardware::graphics::composer3::vts
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
new file mode 100644
index 0000000..50ce462
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/RenderEngineVts.cpp
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/RenderEngineVts.h"
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+
+using ::android::hardware::graphics::mapper::V2_1::IMapper;
+using ::android::renderengine::DisplaySettings;
+using ::android::renderengine::LayerSettings;
+using ::android::renderengine::RenderEngineCreationArgs;
+
+TestRenderEngine::TestRenderEngine(const RenderEngineCreationArgs& args) {
+    mFormat = static_cast<common::PixelFormat>(args.pixelFormat);
+    mRenderEngine = ::android::renderengine::RenderEngine::create(args);
+}
+
+TestRenderEngine::~TestRenderEngine() {
+    mRenderEngine.release();
+}
+
+void TestRenderEngine::setRenderLayers(std::vector<std::shared_ptr<TestLayer>> layers) {
+    sort(layers.begin(), layers.end(),
+         [](const std::shared_ptr<TestLayer>& lhs, const std::shared_ptr<TestLayer>& rhs) -> bool {
+             return lhs->getZOrder() < rhs->getZOrder();
+         });
+
+    if (!mCompositionLayers.empty()) {
+        mCompositionLayers.clear();
+    }
+    for (auto& layer : layers) {
+        LayerSettings settings = layer->toRenderEngineLayerSettings();
+        mCompositionLayers.push_back(settings);
+    }
+}
+
+void TestRenderEngine::initGraphicBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
+                                         uint64_t usage) {
+    mGraphicBuffer = ::android::sp<::android::GraphicBuffer>::make(
+            width, height, static_cast<int32_t>(mFormat), layerCount, usage);
+}
+
+void TestRenderEngine::drawLayers() {
+    ::android::base::unique_fd bufferFence;
+
+    std::vector<::android::renderengine::LayerSettings> compositionLayers;
+    compositionLayers.reserve(mCompositionLayers.size());
+    std::transform(mCompositionLayers.begin(), mCompositionLayers.end(),
+                   std::back_insert_iterator(compositionLayers),
+                   [](::android::renderengine::LayerSettings& settings)
+                           -> ::android::renderengine::LayerSettings { return settings; });
+    auto texture = std::make_shared<::android::renderengine::ExternalTexture>(
+            mGraphicBuffer, *mRenderEngine,
+            ::android::renderengine::ExternalTexture::Usage::WRITEABLE);
+    auto [status, readyFence] = mRenderEngine
+                                        ->drawLayers(mDisplaySettings, compositionLayers, texture,
+                                                     true, std::move(bufferFence))
+                                        .get();
+    int fd = readyFence.release();
+    if (fd != -1) {
+        ASSERT_EQ(0, sync_wait(fd, -1));
+        ASSERT_EQ(0, close(fd));
+    }
+}
+
+void TestRenderEngine::checkColorBuffer(std::vector<Color>& expectedColors) {
+    void* bufferData;
+    ASSERT_EQ(0,
+              mGraphicBuffer->lock(static_cast<uint32_t>(mGraphicBuffer->getUsage()), &bufferData));
+    ReadbackHelper::compareColorBuffers(
+            expectedColors, bufferData, static_cast<int32_t>(mGraphicBuffer->getStride()),
+            mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(), mFormat);
+    ASSERT_EQ(::android::OK, mGraphicBuffer->unlock());
+}
+
+}  // namespace aidl::android::hardware::graphics::composer3::vts
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/GraphicsComposerCallback.h b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/GraphicsComposerCallback.h
new file mode 100644
index 0000000..c359d5e
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/GraphicsComposerCallback.h
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include <aidl/android/hardware/graphics/composer3/BnComposerCallback.h>
+#include <android-base/thread_annotations.h>
+#include <mutex>
+#include <unordered_set>
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop  // ignored "-Wconversion
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+
+class GraphicsComposerCallback : public BnComposerCallback {
+  public:
+    void setVsyncAllowed(bool allowed);
+
+    std::vector<int64_t> getDisplays() const;
+
+    int32_t getInvalidHotplugCount() const;
+
+    int32_t getInvalidRefreshCount() const;
+
+    int32_t getInvalidVsyncCount() const;
+
+    int32_t getInvalidVsyncPeriodChangeCount() const;
+
+    int32_t getInvalidSeamlessPossibleCount() const;
+
+    std::optional<VsyncPeriodChangeTimeline> takeLastVsyncPeriodChangeTimeline();
+
+  private:
+    virtual ::ndk::ScopedAStatus onHotplug(int64_t in_display, bool in_connected) override;
+    virtual ::ndk::ScopedAStatus onRefresh(int64_t in_display) override;
+    virtual ::ndk::ScopedAStatus onSeamlessPossible(int64_t in_display) override;
+    virtual ::ndk::ScopedAStatus onVsync(int64_t in_display, int64_t in_timestamp,
+                                         int32_t in_vsyncPeriodNanos) override;
+    virtual ::ndk::ScopedAStatus onVsyncPeriodTimingChanged(
+            int64_t in_display,
+            const ::aidl::android::hardware::graphics::composer3::VsyncPeriodChangeTimeline&
+                    in_updatedTimeline) override;
+
+    mutable std::mutex mMutex;
+    // the set of all currently connected displays
+    std::unordered_set<int64_t> mDisplays GUARDED_BY(mMutex);
+    // true only when vsync is enabled
+    bool mVsyncAllowed GUARDED_BY(mMutex) = true;
+
+    std::optional<VsyncPeriodChangeTimeline> mTimeline GUARDED_BY(mMutex);
+
+    // track invalid callbacks
+    int32_t mInvalidHotplugCount GUARDED_BY(mMutex) = 0;
+    int32_t mInvalidRefreshCount GUARDED_BY(mMutex) = 0;
+    int32_t mInvalidVsyncCount GUARDED_BY(mMutex) = 0;
+    int32_t mInvalidVsyncPeriodChangeCount GUARDED_BY(mMutex) = 0;
+    int32_t mInvalidSeamlessPossibleCount GUARDED_BY(mMutex) = 0;
+};
+
+}  // namespace aidl::android::hardware::graphics::composer3::vts
\ No newline at end of file
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/ReadbackVts.h b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/ReadbackVts.h
new file mode 100644
index 0000000..60a036e
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/ReadbackVts.h
@@ -0,0 +1,217 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include <GraphicsComposerCallback.h>
+#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
+#include <android-base/unique_fd.h>
+#include <android/hardware/graphics/composer3/ComposerClientReader.h>
+#include <android/hardware/graphics/composer3/ComposerClientWriter.h>
+#include <mapper-vts/2.1/MapperVts.h>
+#include <renderengine/RenderEngine.h>
+#include <ui/GraphicBuffer.h>
+
+#include <memory>
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop  // ignored "-Wconversion
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+
+using ::android::renderengine::LayerSettings;
+using common::Dataspace;
+using common::PixelFormat;
+using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
+
+static const Color BLACK = {0, 0, 0, static_cast<int8_t>(0xff)};
+static const Color RED = {static_cast<int8_t>(0xff), 0, 0, static_cast<int8_t>(0xff)};
+static const Color TRANSLUCENT_RED = {static_cast<int8_t>(0xff), 0, 0, 0x33};
+static const Color GREEN = {0, static_cast<int8_t>(0xff), 0, static_cast<int8_t>(0xff)};
+static const Color BLUE = {0, 0, static_cast<int8_t>(0xff), static_cast<int8_t>(0xff)};
+static const Color WHITE = {static_cast<int8_t>(0xff), static_cast<int8_t>(0xff),
+                            static_cast<int8_t>(0xff), static_cast<int8_t>(0xff)};
+
+class TestRenderEngine;
+
+class TestLayer {
+  public:
+    TestLayer(const std::shared_ptr<IComposerClient>& client, int64_t display)
+        : mDisplay(display), mComposerClient(client) {
+        client->createLayer(display, kBufferSlotCount, &mLayer);
+    }
+
+    // ComposerClient will take care of destroying layers, no need to explicitly
+    // call destroyLayers here
+    virtual ~TestLayer(){};
+
+    virtual void write(ComposerClientWriter& writer);
+    virtual LayerSettings toRenderEngineLayerSettings();
+
+    void setDisplayFrame(Rect frame) { mDisplayFrame = frame; }
+    void setSourceCrop(FRect crop) { mSourceCrop = crop; }
+    void setZOrder(uint32_t z) { mZOrder = z; }
+
+    void setSurfaceDamage(std::vector<Rect> surfaceDamage) {
+        mSurfaceDamage = std::move(surfaceDamage);
+    }
+
+    void setTransform(Transform transform) { mTransform = transform; }
+    void setAlpha(float alpha) { mAlpha = alpha; }
+    void setBlendMode(BlendMode blendMode) { mBlendMode = blendMode; }
+
+    BlendMode getBlendMode() const { return mBlendMode; }
+
+    uint32_t getZOrder() const { return mZOrder; }
+
+    float getAlpha() const { return mAlpha; }
+
+    int64_t getLayer() const { return mLayer; }
+
+  protected:
+    int64_t mDisplay;
+    int64_t mLayer;
+    Rect mDisplayFrame = {0, 0, 0, 0};
+    std::vector<Rect> mSurfaceDamage;
+    Transform mTransform = static_cast<Transform>(0);
+    FRect mSourceCrop = {0, 0, 0, 0};
+    static constexpr uint32_t kBufferSlotCount = 64;
+    float mAlpha = 1.0;
+    BlendMode mBlendMode = BlendMode::NONE;
+    uint32_t mZOrder = 0;
+
+  private:
+    std::shared_ptr<IComposerClient> const mComposerClient;
+};
+
+class TestColorLayer : public TestLayer {
+  public:
+    TestColorLayer(const std::shared_ptr<IComposerClient>& client, int64_t display)
+        : TestLayer{client, display} {}
+
+    void write(ComposerClientWriter& writer) override;
+
+    LayerSettings toRenderEngineLayerSettings() override;
+
+    void setColor(Color color) { mColor = color; }
+
+  private:
+    Color mColor = WHITE;
+};
+
+class TestBufferLayer : public TestLayer {
+  public:
+    TestBufferLayer(const std::shared_ptr<IComposerClient>& client,
+                    const ::android::sp<::android::GraphicBuffer>& graphicBuffer,
+                    TestRenderEngine& renderEngine, int64_t display, uint32_t width,
+                    uint32_t height, common::PixelFormat format,
+                    Composition composition = Composition::DEVICE);
+
+    void write(ComposerClientWriter& writer) override;
+
+    LayerSettings toRenderEngineLayerSettings() override;
+
+    void fillBuffer(std::vector<Color>& expectedColors);
+
+    void setBuffer(std::vector<Color> colors);
+
+    void setDataspace(Dataspace dataspace, ComposerClientWriter& writer);
+
+    void setToClientComposition(ComposerClientWriter& writer);
+
+    uint32_t getWidth() const { return mWidth; }
+
+    uint32_t getHeight() const { return mHeight; }
+
+    ::android::Rect getAccessRegion() const { return mAccessRegion; }
+
+    uint32_t getLayerCount() const { return mLayerCount; }
+
+  protected:
+    Composition mComposition;
+    ::android::sp<::android::GraphicBuffer> mGraphicBuffer;
+    TestRenderEngine& mRenderEngine;
+    int32_t mFillFence;
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint32_t mLayerCount;
+    PixelFormat mPixelFormat;
+    uint32_t mUsage;
+    uint32_t mStride;
+    ::android::Rect mAccessRegion;
+};
+
+class ReadbackHelper {
+  public:
+    static std::string getColorModeString(ColorMode mode);
+
+    static std::string getDataspaceString(Dataspace dataspace);
+
+    static Dataspace getDataspaceForColorMode(ColorMode mode);
+
+    static int32_t GetBytesPerPixel(PixelFormat pixelFormat);
+
+    static void fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData,
+                           PixelFormat pixelFormat, std::vector<Color> desiredPixelColors);
+
+    static void clearColors(std::vector<Color>& expectedColors, int32_t width, int32_t height,
+                            int32_t displayWidth);
+
+    static void fillColorsArea(std::vector<Color>& expectedColors, int32_t stride, Rect area,
+                               Color color);
+
+    static bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace);
+
+    static const std::vector<ColorMode> colorModes;
+    static const std::vector<Dataspace> dataspaces;
+
+    static void compareColorBuffers(std::vector<Color>& expectedColors, void* bufferData,
+                                    const int32_t stride, const uint32_t width,
+                                    const uint32_t height, PixelFormat pixelFormat);
+};
+
+class ReadbackBuffer {
+  public:
+    ReadbackBuffer(int64_t display, const std::shared_ptr<IComposerClient>& client,
+                   const ::android::sp<::android::GraphicBuffer>& graphicBuffer, int32_t width,
+                   int32_t height, common::PixelFormat pixelFormat, common::Dataspace dataspace);
+
+    void setReadbackBuffer();
+
+    void checkReadbackBuffer(std::vector<Color> expectedColors);
+
+    ::android::sp<::android::GraphicBuffer> allocate();
+
+  protected:
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint32_t mLayerCount;
+    uint32_t mUsage;
+    uint32_t mStride;
+    PixelFormat mPixelFormat;
+    Dataspace mDataspace;
+    int64_t mDisplay;
+    ::android::sp<::android::GraphicBuffer> mGraphicBuffer;
+    std::shared_ptr<IComposerClient> mComposerClient;
+    ::android::Rect mAccessRegion;
+    native_handle_t mBufferHandle;
+};
+
+}  // namespace aidl::android::hardware::graphics::composer3::vts
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/RenderEngineVts.h b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/RenderEngineVts.h
new file mode 100644
index 0000000..2798e09
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/RenderEngineVts.h
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include <ReadbackVts.h>
+#include <mapper-vts/2.1/MapperVts.h>
+#include <math/half.h>
+#include <math/vec3.h>
+#include <renderengine/ExternalTexture.h>
+#include <renderengine/RenderEngine.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop  // ignored "-Wconversion
+
+namespace aidl::android::hardware::graphics::composer3::vts {
+
+using ::android::hardware::graphics::mapper::V2_1::IMapper;
+using ::android::renderengine::DisplaySettings;
+using ::android::renderengine::ExternalTexture;
+using ::android::renderengine::RenderEngineCreationArgs;
+
+class TestRenderEngine {
+  public:
+    static constexpr uint32_t sMaxFrameBufferAcquireBuffers = 2;
+
+    TestRenderEngine(const RenderEngineCreationArgs& args);
+    ~TestRenderEngine();
+
+    void setRenderLayers(std::vector<std::shared_ptr<TestLayer>> layers);
+    void initGraphicBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint64_t usage);
+    void setDisplaySettings(DisplaySettings& displaySettings) {
+        mDisplaySettings = displaySettings;
+    };
+    void drawLayers();
+    void checkColorBuffer(std::vector<Color>& expectedColors);
+
+    ::android::renderengine::RenderEngine& getInternalRenderEngine() { return *mRenderEngine; }
+
+  private:
+    common::PixelFormat mFormat;
+    std::vector<::android::renderengine::LayerSettings> mCompositionLayers;
+    std::unique_ptr<::android::renderengine::RenderEngine> mRenderEngine;
+    std::vector<::android::renderengine::LayerSettings> mRenderLayers;
+    ::android::sp<::android::GraphicBuffer> mGraphicBuffer;
+
+    DisplaySettings mDisplaySettings;
+};
+
+}  // namespace aidl::android::hardware::graphics::composer3::vts
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
new file mode 100644
index 0000000..f9e35e9
--- /dev/null
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <limits>
+#include <memory>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <aidl/android/hardware/graphics/composer3/ClientTargetProperty.h>
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+#include <aidl/android/hardware/graphics/composer3/CommandResultPayload.h>
+
+
+#include <log/log.h>
+#include <sync/sync.h>
+
+
+using aidl::android::hardware::graphics::common::Dataspace;
+
+namespace aidl::android::hardware::graphics::composer3 {
+
+class ComposerClientReader {
+  public:
+    ~ComposerClientReader() { resetData(); }
+
+    // Parse and execute commands from the command queue.  The commands are
+    // actually return values from the server and will be saved in ReturnData.
+    void parse(std::vector<CommandResultPayload>&& results) {
+        resetData();
+
+        for (auto& result : results) {
+            switch (result.getTag()) {
+                case CommandResultPayload::Tag::error:
+                    parseSetError(std::move(result.get<CommandResultPayload::Tag::error>()));
+                    break;
+                case CommandResultPayload::Tag::changedCompositionTypes:
+                    parseSetChangedCompositionTypes(std::move(
+                            result.get<CommandResultPayload::Tag::changedCompositionTypes>()));
+                    break;
+                case CommandResultPayload::Tag::displayRequest:
+                    parseSetDisplayRequests(
+                            std::move(result.get<CommandResultPayload::Tag::displayRequest>()));
+                    break;
+                case CommandResultPayload::Tag::presentFence:
+                    parseSetPresentFence(
+                            std::move(result.get<CommandResultPayload::Tag::presentFence>()));
+                    break;
+                case CommandResultPayload::Tag::releaseFences:
+                    parseSetReleaseFences(
+                            std::move(result.get<CommandResultPayload::Tag::releaseFences>()));
+                    break;
+                case CommandResultPayload::Tag::presentOrValidateResult:
+                    parseSetPresentOrValidateDisplayResult(std::move(
+                            result.get<CommandResultPayload::Tag::presentOrValidateResult>()));
+                    break;
+                case CommandResultPayload::Tag::clientTargetProperty:
+                    parseSetClientTargetProperty(std::move(
+                            result.get<CommandResultPayload::Tag::clientTargetProperty>()));
+                    break;
+            }
+        }
+    }
+
+    std::vector<CommandError> takeErrors() { return std::move(mErrors); }
+
+    void hasChanges(int64_t display, uint32_t* outNumChangedCompositionTypes,
+                    uint32_t* outNumLayerRequestMasks) const {
+        auto found = mReturnData.find(display);
+        if (found == mReturnData.end()) {
+            *outNumChangedCompositionTypes = 0;
+            *outNumLayerRequestMasks = 0;
+            return;
+        }
+
+        const ReturnData& data = found->second;
+
+        *outNumChangedCompositionTypes = static_cast<uint32_t>(data.changedLayers.size());
+        *outNumLayerRequestMasks = static_cast<uint32_t>(data.displayRequests.layerRequests.size());
+    }
+
+    // Get and clear saved changed composition types.
+    std::vector<ChangedCompositionLayer> takeChangedCompositionTypes(int64_t display) {
+        auto found = mReturnData.find(display);
+        if (found == mReturnData.end()) {
+            return {};
+        }
+
+        ReturnData& data = found->second;
+        return std::move(data.changedLayers);
+    }
+
+    // Get and clear saved display requests.
+    DisplayRequest takeDisplayRequests(int64_t display) {
+        auto found = mReturnData.find(display);
+        if (found == mReturnData.end()) {
+            return {};
+        }
+
+        ReturnData& data = found->second;
+        return std::move(data.displayRequests);
+    }
+
+    // Get and clear saved release fences.
+    std::vector<ReleaseFences::Layer> takeReleaseFences(int64_t display) {
+        auto found = mReturnData.find(display);
+        if (found == mReturnData.end()) {
+            return {};
+        }
+
+        ReturnData& data = found->second;
+        return std::move(data.releasedLayers);
+    }
+
+    // Get and clear saved present fence.
+    ndk::ScopedFileDescriptor takePresentFence(int64_t display) {
+        auto found = mReturnData.find(display);
+        if (found == mReturnData.end()) {
+            return {};
+        }
+
+        ReturnData& data = found->second;
+        return std::move(data.presentFence);
+    }
+
+    // Get what stage succeeded during PresentOrValidate: Present or Validate
+    std::optional<PresentOrValidate::Result> takePresentOrValidateStage(int64_t display) {
+        auto found = mReturnData.find(display);
+        if (found == mReturnData.end()) {
+            return std::nullopt;
+        }
+        ReturnData& data = found->second;
+        return data.presentOrValidateState;
+    }
+
+    // Get the client target properties requested by hardware composer.
+    ClientTargetPropertyWithNits takeClientTargetProperty(int64_t display) {
+        auto found = mReturnData.find(display);
+
+        // If not found, return the default values.
+        if (found == mReturnData.end()) {
+            return ClientTargetPropertyWithNits{
+                    .clientTargetProperty = {common::PixelFormat::RGBA_8888, Dataspace::UNKNOWN},
+                    .whitePointNits = -1.f,
+            };
+        }
+
+        ReturnData& data = found->second;
+        return std::move(data.clientTargetProperty);
+    }
+
+  private:
+    void resetData() {
+        mErrors.clear();
+        mReturnData.clear();
+    }
+
+    void parseSetError(CommandError&& error) { mErrors.emplace_back(error); }
+
+    void parseSetChangedCompositionTypes(ChangedCompositionTypes&& changedCompositionTypes) {
+        auto& data = mReturnData[changedCompositionTypes.display];
+        data.changedLayers = std::move(changedCompositionTypes.layers);
+    }
+
+    void parseSetDisplayRequests(DisplayRequest&& displayRequest) {
+        auto& data = mReturnData[displayRequest.display];
+        data.displayRequests = std::move(displayRequest);
+    }
+
+    void parseSetPresentFence(PresentFence&& presentFence) {
+        auto& data = mReturnData[presentFence.display];
+        data.presentFence = std::move(presentFence.fence);
+    }
+
+    void parseSetReleaseFences(ReleaseFences&& releaseFences) {
+        auto& data = mReturnData[releaseFences.display];
+        data.releasedLayers = std::move(releaseFences.layers);
+    }
+
+    void parseSetPresentOrValidateDisplayResult(const PresentOrValidate&& presentOrValidate) {
+        auto& data = mReturnData[presentOrValidate.display];
+        data.presentOrValidateState = std::move(presentOrValidate.result);
+    }
+
+    void parseSetClientTargetProperty(const ClientTargetPropertyWithNits&& clientTargetProperty) {
+        auto& data = mReturnData[clientTargetProperty.display];
+        data.clientTargetProperty = std::move(clientTargetProperty);
+    }
+
+    struct ReturnData {
+        DisplayRequest displayRequests;
+        std::vector<ChangedCompositionLayer> changedLayers;
+        ndk::ScopedFileDescriptor presentFence;
+        std::vector<ReleaseFences::Layer> releasedLayers;
+        PresentOrValidate::Result presentOrValidateState;
+
+        ClientTargetPropertyWithNits clientTargetProperty = {
+                .clientTargetProperty = {common::PixelFormat::RGBA_8888, Dataspace::UNKNOWN},
+                .whitePointNits = -1.f,
+        };
+    };
+
+    std::vector<CommandError> mErrors;
+    std::unordered_map<int64_t, ReturnData> mReturnData;
+};
+
+}  // namespace aidl::android::hardware::graphics::composer3
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
new file mode 100644
index 0000000..16d63e5
--- /dev/null
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <limits>
+#include <memory>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <aidl/android/hardware/graphics/common/BlendMode.h>
+#include <aidl/android/hardware/graphics/composer3/Color.h>
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+#include <aidl/android/hardware/graphics/composer3/FloatColor.h>
+#include <aidl/android/hardware/graphics/composer3/PerFrameMetadata.h>
+#include <aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h>
+
+#include <aidl/android/hardware/graphics/composer3/DisplayCommand.h>
+
+#include <aidl/android/hardware/graphics/common/ColorTransform.h>
+#include <aidl/android/hardware/graphics/common/FRect.h>
+#include <aidl/android/hardware/graphics/common/Rect.h>
+#include <aidl/android/hardware/graphics/common/Transform.h>
+
+#include <log/log.h>
+#include <sync/sync.h>
+
+#include <aidlcommonsupport/NativeHandle.h>
+
+using aidl::android::hardware::graphics::common::BlendMode;
+using aidl::android::hardware::graphics::common::ColorTransform;
+using aidl::android::hardware::graphics::common::Dataspace;
+using aidl::android::hardware::graphics::common::FRect;
+using aidl::android::hardware::graphics::common::Rect;
+using aidl::android::hardware::graphics::common::Transform;
+
+using namespace aidl::android::hardware::graphics::composer3;
+
+using aidl::android::hardware::common::NativeHandle;
+
+namespace aidl::android::hardware::graphics::composer3 {
+
+class ComposerClientWriter {
+  public:
+    static constexpr std::optional<ClockMonotonicTimestamp> kNoTimestamp = std::nullopt;
+
+    ComposerClientWriter() { reset(); }
+
+    virtual ~ComposerClientWriter() { reset(); }
+
+    void reset() {
+        mDisplayCommand.reset();
+        mLayerCommand.reset();
+        mCommands.clear();
+    }
+
+    void setColorTransform(int64_t display, const float* matrix) {
+        std::vector<float> matVec;
+        matVec.reserve(16);
+        matVec.assign(matrix, matrix + 16);
+        getDisplayCommand(display).colorTransformMatrix.emplace(std::move(matVec));
+    }
+
+    void setClientTarget(int64_t display, uint32_t slot, const native_handle_t* target,
+                         int acquireFence, Dataspace dataspace, const std::vector<Rect>& damage) {
+        ClientTarget clientTargetCommand;
+        clientTargetCommand.buffer = getBuffer(slot, target, acquireFence);
+        clientTargetCommand.dataspace = dataspace;
+        clientTargetCommand.damage.assign(damage.begin(), damage.end());
+        getDisplayCommand(display).clientTarget.emplace(std::move(clientTargetCommand));
+    }
+
+    void setOutputBuffer(int64_t display, uint32_t slot, const native_handle_t* buffer,
+                         int releaseFence) {
+        getDisplayCommand(display).virtualDisplayOutputBuffer.emplace(
+                getBuffer(slot, buffer, releaseFence));
+    }
+
+    void validateDisplay(int64_t display,
+                         std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
+        auto& command = getDisplayCommand(display);
+        command.expectedPresentTime = expectedPresentTime;
+        command.validateDisplay = true;
+    }
+
+    void presentOrvalidateDisplay(int64_t display,
+                                  std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
+        auto& command = getDisplayCommand(display);
+        command.expectedPresentTime = expectedPresentTime;
+        command.presentOrValidateDisplay = true;
+    }
+
+    void acceptDisplayChanges(int64_t display) {
+        getDisplayCommand(display).acceptDisplayChanges = true;
+    }
+
+    void presentDisplay(int64_t display) { getDisplayCommand(display).presentDisplay = true; }
+
+    void setLayerCursorPosition(int64_t display, int64_t layer, int32_t x, int32_t y) {
+        common::Point cursorPosition;
+        cursorPosition.x = x;
+        cursorPosition.y = y;
+        getLayerCommand(display, layer).cursorPosition.emplace(std::move(cursorPosition));
+    }
+
+    void setLayerBuffer(int64_t display, int64_t layer, uint32_t slot,
+                        const native_handle_t* buffer, int acquireFence) {
+        getLayerCommand(display, layer).buffer = getBuffer(slot, buffer, acquireFence);
+    }
+
+    void setLayerSurfaceDamage(int64_t display, int64_t layer, const std::vector<Rect>& damage) {
+        getLayerCommand(display, layer).damage.emplace(damage.begin(), damage.end());
+    }
+
+    void setLayerBlendMode(int64_t display, int64_t layer, BlendMode mode) {
+        ParcelableBlendMode parcelableBlendMode;
+        parcelableBlendMode.blendMode = mode;
+        getLayerCommand(display, layer).blendMode.emplace(std::move(parcelableBlendMode));
+    }
+
+    void setLayerColor(int64_t display, int64_t layer, Color color) {
+        getLayerCommand(display, layer).color.emplace(std::move(color));
+    }
+
+    void setLayerCompositionType(int64_t display, int64_t layer, Composition type) {
+        ParcelableComposition compositionPayload;
+        compositionPayload.composition = type;
+        getLayerCommand(display, layer).composition.emplace(std::move(compositionPayload));
+    }
+
+    void setLayerDataspace(int64_t display, int64_t layer, Dataspace dataspace) {
+        ParcelableDataspace dataspacePayload;
+        dataspacePayload.dataspace = dataspace;
+        getLayerCommand(display, layer).dataspace.emplace(std::move(dataspacePayload));
+    }
+
+    void setLayerDisplayFrame(int64_t display, int64_t layer, const Rect& frame) {
+        getLayerCommand(display, layer).displayFrame.emplace(frame);
+    }
+
+    void setLayerPlaneAlpha(int64_t display, int64_t layer, float alpha) {
+        PlaneAlpha planeAlpha;
+        planeAlpha.alpha = alpha;
+        getLayerCommand(display, layer).planeAlpha.emplace(std::move(planeAlpha));
+    }
+
+    void setLayerSidebandStream(int64_t display, int64_t layer, const native_handle_t* stream) {
+        NativeHandle handle;
+        if (stream) handle = ::android::dupToAidl(stream);
+        getLayerCommand(display, layer).sidebandStream.emplace(std::move(handle));
+    }
+
+    void setLayerSourceCrop(int64_t display, int64_t layer, const FRect& crop) {
+        getLayerCommand(display, layer).sourceCrop.emplace(crop);
+    }
+
+    void setLayerTransform(int64_t display, int64_t layer, Transform transform) {
+        ParcelableTransform transformPayload;
+        transformPayload.transform = transform;
+        getLayerCommand(display, layer).transform.emplace(std::move(transformPayload));
+    }
+
+    void setLayerVisibleRegion(int64_t display, int64_t layer, const std::vector<Rect>& visible) {
+        getLayerCommand(display, layer).visibleRegion.emplace(visible.begin(), visible.end());
+    }
+
+    void setLayerZOrder(int64_t display, int64_t layer, uint32_t z) {
+        ZOrder zorder;
+        zorder.z = z;
+        getLayerCommand(display, layer).z.emplace(std::move(zorder));
+    }
+
+    void setLayerPerFrameMetadata(int64_t display, int64_t layer,
+                                  const std::vector<PerFrameMetadata>& metadataVec) {
+        getLayerCommand(display, layer)
+                .perFrameMetadata.emplace(metadataVec.begin(), metadataVec.end());
+    }
+
+    void setLayerColorTransform(int64_t display, int64_t layer, const float* matrix) {
+        getLayerCommand(display, layer).colorTransform.emplace(matrix, matrix + 16);
+    }
+
+    void setLayerPerFrameMetadataBlobs(int64_t display, int64_t layer,
+                                       const std::vector<PerFrameMetadataBlob>& metadata) {
+        getLayerCommand(display, layer)
+                .perFrameMetadataBlob.emplace(metadata.begin(), metadata.end());
+    }
+
+    void setLayerFloatColor(int64_t display, int64_t layer, FloatColor color) {
+        getLayerCommand(display, layer).floatColor.emplace(color);
+    }
+
+    void setLayerWhitePointNits(int64_t display, int64_t layer, float whitePointNits) {
+        getLayerCommand(display, layer)
+                .whitePointNits.emplace(WhitePointNits{.nits = whitePointNits});
+    }
+
+    const std::vector<DisplayCommand>& getPendingCommands() {
+        flushLayerCommand();
+        flushDisplayCommand();
+        return mCommands;
+    }
+
+  private:
+    std::optional<DisplayCommand> mDisplayCommand;
+    std::optional<LayerCommand> mLayerCommand;
+    std::vector<DisplayCommand> mCommands;
+
+    Buffer getBuffer(int slot, const native_handle_t* bufferHandle, int fence) {
+        Buffer bufferCommand;
+        bufferCommand.slot = slot;
+        if (bufferHandle) bufferCommand.handle.emplace(::android::dupToAidl(bufferHandle));
+        if (fence > 0) bufferCommand.fence = ::ndk::ScopedFileDescriptor(fence);
+        return bufferCommand;
+    }
+
+    void flushLayerCommand() {
+        if (mLayerCommand.has_value()) {
+            mDisplayCommand->layers.emplace_back(std::move(*mLayerCommand));
+            mLayerCommand.reset();
+        }
+    }
+
+    void flushDisplayCommand() {
+        if (mDisplayCommand.has_value()) {
+            mCommands.emplace_back(std::move(*mDisplayCommand));
+            mDisplayCommand.reset();
+        }
+    }
+
+    DisplayCommand& getDisplayCommand(int64_t display) {
+        if (!mDisplayCommand.has_value() || mDisplayCommand->display != display) {
+            flushLayerCommand();
+            flushDisplayCommand();
+            mDisplayCommand.emplace();
+            mDisplayCommand->display = display;
+        }
+        return *mDisplayCommand;
+    }
+
+    LayerCommand& getLayerCommand(int64_t display, int64_t layer) {
+        getDisplayCommand(display);
+        if (!mLayerCommand.has_value() || mLayerCommand->layer != layer) {
+            flushLayerCommand();
+            mLayerCommand.emplace();
+            mLayerCommand->layer = layer;
+        }
+        return *mLayerCommand;
+    }
+};
+
+}  // namespace aidl::android::hardware::graphics::composer3
diff --git a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
index 4187dd1..6c90af4 100644
--- a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
+++ b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
@@ -327,6 +327,39 @@
 }
 
 /**
+ * Test IMapper::lockYCbCr.  This locks a YCbCr_P010 buffer and verifies that it's initialized.
+ */
+TEST_P(GraphicsMapperHidlTest, LockYCbCrP010) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::YCBCR_P010;
+
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
+
+    ASSERT_NE(nullptr, bufferHandle);
+
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    int fence = -1;
+    YCbCrLayout y_cb_cr_layout{};
+    // lock buffer
+    ASSERT_NO_FATAL_FAILURE(y_cb_cr_layout =
+                                    mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
+
+    ASSERT_NE(nullptr, &y_cb_cr_layout);
+    EXPECT_EQ(stride, info.width);
+    EXPECT_EQ(y_cb_cr_layout.yStride, info.height * 2);
+    EXPECT_EQ(y_cb_cr_layout.cStride, y_cb_cr_layout.yStride);
+    EXPECT_EQ(4, y_cb_cr_layout.chromaStep);
+
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+    if (fence >= 0) {
+        close(fence);
+    }
+}
+
+/**
  * Test IMapper::lockYCbCr.  This locks a YV12 buffer, and makes sure we can
  * write to and read from it.
  */
diff --git a/graphics/mapper/4.0/vts/functional/Android.bp b/graphics/mapper/4.0/vts/functional/Android.bp
index 032bc0f..65bc380 100644
--- a/graphics/mapper/4.0/vts/functional/Android.bp
+++ b/graphics/mapper/4.0/vts/functional/Android.bp
@@ -28,7 +28,7 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGraphicsMapperV4_0TargetTest.cpp"],
     static_libs: [
-        "android.hardware.graphics.common-V2-ndk",
+        "android.hardware.graphics.common-V3-ndk",
         "android.hardware.graphics.mapper@4.0-vts",
         "libgralloctypes",
         "libsync",
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index f55a6b7..2ab9c01 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -59,6 +59,12 @@
 using DecodeFunction = std::function<void(const IMapper::BufferDescriptorInfo& descriptorInfo,
                                           const hidl_vec<uint8_t>& vec)>;
 
+struct YCbCr {
+    android_ycbcr yCbCr;
+    int64_t horizontalSubSampling;
+    int64_t verticalSubSampling;
+};
+
 class GraphicsMapperHidlTest
     : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
   protected:
@@ -215,8 +221,8 @@
                 }
                 ASSERT_EQ(0, planeLayoutComponent.offsetInBits % 8);
 
-                uint8_t* tmpData =
-                        data + planeLayout.offsetInBytes + (planeLayoutComponent.offsetInBits / 8);
+                uint8_t* tmpData = data + planeLayout.offsetInBytes +
+                                   bitsToBytes(planeLayoutComponent.offsetInBits);
                 uint64_t sampleIncrementInBytes;
 
                 auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
@@ -271,6 +277,96 @@
         ASSERT_NE(nullptr, outYCbCr->cr);
     }
 
+    YCbCr getAndroidYCbCr_P010(const native_handle_t* bufferHandle, uint8_t* data) {
+        YCbCr yCbCr_P010;
+        hidl_vec<uint8_t> vec;
+        EXPECT_EQ(Error::NONE,
+                  mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
+        std::vector<PlaneLayout> planeLayouts;
+        EXPECT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
+        EXPECT_EQ(2, planeLayouts.size());
+        EXPECT_EQ(1, planeLayouts[0].components.size());
+        EXPECT_EQ(2, planeLayouts[1].components.size());
+
+        yCbCr_P010.yCbCr.y = nullptr;
+        yCbCr_P010.yCbCr.cb = nullptr;
+        yCbCr_P010.yCbCr.cr = nullptr;
+        yCbCr_P010.yCbCr.ystride = 0;
+        yCbCr_P010.yCbCr.cstride = 0;
+        yCbCr_P010.yCbCr.chroma_step = 0;
+        int64_t cb_offset = 0;
+        int64_t cr_offset = 0;
+
+        for (const auto& planeLayout : planeLayouts) {
+            for (const auto& planeLayoutComponent : planeLayout.components) {
+                if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
+                    continue;
+                }
+
+                uint8_t* tmpData = data + planeLayout.offsetInBytes +
+                                   bitsToBytes(planeLayoutComponent.offsetInBits);
+                uint64_t sampleIncrementInBytes = 0;
+                auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
+                switch (type) {
+                    case PlaneLayoutComponentType::Y:
+                        // For specs refer:
+                        // https://docs.microsoft.com/en-us/windows/win32/medfound/10-bit-and-16-bit-yuv-video-formats
+                        EXPECT_EQ(6, planeLayoutComponent.offsetInBits);
+                        EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.y);
+                        EXPECT_EQ(10, planeLayoutComponent.sizeInBits);
+                        EXPECT_EQ(16, planeLayout.sampleIncrementInBits);
+
+                        yCbCr_P010.yCbCr.y = tmpData;
+                        yCbCr_P010.yCbCr.ystride = planeLayout.strideInBytes;
+                        break;
+
+                    case PlaneLayoutComponentType::CB:
+                    case PlaneLayoutComponentType::CR:
+                        sampleIncrementInBytes = bitsToBytes(planeLayout.sampleIncrementInBits);
+                        EXPECT_EQ(4, sampleIncrementInBytes);
+
+                        if (yCbCr_P010.yCbCr.cstride == 0 && yCbCr_P010.yCbCr.chroma_step == 0) {
+                            yCbCr_P010.yCbCr.cstride = planeLayout.strideInBytes;
+                            yCbCr_P010.yCbCr.chroma_step = sampleIncrementInBytes;
+                        } else {
+                            EXPECT_EQ(yCbCr_P010.yCbCr.cstride, planeLayout.strideInBytes);
+                            EXPECT_EQ(yCbCr_P010.yCbCr.chroma_step, sampleIncrementInBytes);
+                        }
+
+                        if (yCbCr_P010.horizontalSubSampling == 0 &&
+                            yCbCr_P010.verticalSubSampling == 0) {
+                            yCbCr_P010.horizontalSubSampling = planeLayout.horizontalSubsampling;
+                            yCbCr_P010.verticalSubSampling = planeLayout.verticalSubsampling;
+                        } else {
+                            EXPECT_EQ(yCbCr_P010.horizontalSubSampling,
+                                      planeLayout.horizontalSubsampling);
+                            EXPECT_EQ(yCbCr_P010.verticalSubSampling,
+                                      planeLayout.verticalSubsampling);
+                        }
+
+                        if (type == PlaneLayoutComponentType::CB) {
+                            EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cb);
+                            yCbCr_P010.yCbCr.cb = tmpData;
+                            cb_offset = planeLayoutComponent.offsetInBits;
+                        } else {
+                            EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cr);
+                            yCbCr_P010.yCbCr.cr = tmpData;
+                            cr_offset = planeLayoutComponent.offsetInBits;
+                        }
+                        break;
+                    default:
+                        break;
+                };
+            }
+        }
+
+        EXPECT_EQ(cb_offset + bytesToBits(2), cr_offset);
+        EXPECT_NE(nullptr, yCbCr_P010.yCbCr.y);
+        EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cb);
+        EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cr);
+        return yCbCr_P010;
+    }
+
     void fillRGBA8888(uint8_t* data, uint32_t height, size_t strideInBytes, size_t widthInBytes,
                       uint32_t seed = 0) {
         for (uint32_t y = 0; y < height; y++) {
@@ -297,9 +393,9 @@
         }
     }
 
-    void traverseYCbCr888Data(const android_ycbcr& yCbCr, int32_t width, int32_t height,
-                              int64_t hSubsampling, int64_t vSubsampling,
-                              std::function<void(uint8_t*, uint8_t)> traverseFuncion) {
+    void traverseYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
+                           int64_t hSubsampling, int64_t vSubsampling,
+                           std::function<void(uint8_t*, uint8_t)> traverseFuncion) {
         auto yData = static_cast<uint8_t*>(yCbCr.y);
         auto cbData = static_cast<uint8_t*>(yCbCr.cb);
         auto crData = static_cast<uint8_t*>(yCbCr.cr);
@@ -327,21 +423,25 @@
         }
     }
 
-    void fillYCbCr888Data(const android_ycbcr& yCbCr, int32_t width, int32_t height,
-                          int64_t hSubsampling, int64_t vSubsampling) {
-        traverseYCbCr888Data(yCbCr, width, height, hSubsampling, vSubsampling,
-                             [](auto address, auto fillingData) { *address = fillingData; });
+    void fillYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
+                       int64_t hSubsampling, int64_t vSubsampling) {
+        traverseYCbCrData(yCbCr, width, height, hSubsampling, vSubsampling,
+                          [](auto address, auto fillingData) { *address = fillingData; });
     }
 
-    void verifyYCbCr888Data(const android_ycbcr& yCbCr, int32_t width, int32_t height,
-                            int64_t hSubsampling, int64_t vSubsampling) {
-        traverseYCbCr888Data(
+    void verifyYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
+                         int64_t hSubsampling, int64_t vSubsampling) {
+        traverseYCbCrData(
                 yCbCr, width, height, hSubsampling, vSubsampling,
                 [](auto address, auto expectedData) { EXPECT_EQ(*address, expectedData); });
     }
 
     bool isEqual(float a, float b) { return abs(a - b) < 0.0001; }
 
+    uint64_t bitsToBytes(int64_t bits) { return bits / 8; }
+
+    uint64_t bytesToBits(int64_t bytes) { return bytes * 8; }
+
     std::unique_ptr<Gralloc> mGralloc;
     IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
     static const std::set<StandardMetadataType> sRequiredMetadataTypes;
@@ -645,7 +745,7 @@
     ASSERT_EQ(crData + 1, cbData);
     ASSERT_EQ(2, yCbCr.chroma_step);
 
-    fillYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+    fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
 
     ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
 
@@ -656,7 +756,7 @@
     ASSERT_NO_FATAL_FAILURE(
             getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
 
-    verifyYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+    verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
 
     ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
 }
@@ -744,7 +844,7 @@
     ASSERT_EQ(crData + yCbCr.cstride * info.height / vSubsampling, cbData);
     ASSERT_EQ(1, yCbCr.chroma_step);
 
-    fillYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+    fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
 
     ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
 
@@ -755,7 +855,7 @@
     ASSERT_NO_FATAL_FAILURE(
             getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
 
-    verifyYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+    verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
 
     ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
 }
@@ -788,7 +888,7 @@
     ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
     ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
 
-    fillYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+    fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
 
     ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
 
@@ -799,7 +899,7 @@
     ASSERT_NO_FATAL_FAILURE(
             getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
 
-    verifyYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+    verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
 
     ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
 }
@@ -888,6 +988,42 @@
     ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
 }
 
+TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_P010) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::YCBCR_P010;
+
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(
+            bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride));
+
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    unique_fd fence;
+    uint8_t* data;
+
+    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
+                                                                        region, fence.release())));
+
+    YCbCr yCbCr;
+    ASSERT_NO_FATAL_FAILURE(yCbCr = getAndroidYCbCr_P010(bufferHandle, data));
+
+    constexpr uint32_t kCbCrSubSampleFactor = 2;
+    ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.horizontalSubSampling);
+    ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.verticalSubSampling);
+
+    ASSERT_EQ(0, info.height % 2);
+
+    // fill the data
+    fillYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling,
+                  yCbCr.verticalSubSampling);
+    // verify the YCbCr data
+    verifyYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling,
+                    yCbCr.verticalSubSampling);
+
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
+}
+
 /**
  * Test IMapper::unlock with bad access region
  */
@@ -1346,6 +1482,18 @@
 }
 
 /**
+ * Test IMapper::get(Smpte2094_10)
+ */
+TEST_P(GraphicsMapperHidlTest, GetSmpte2094_10) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_10,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                std::optional<std::vector<uint8_t>> smpte2094_10;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &smpte2094_10));
+                EXPECT_FALSE(smpte2094_10.has_value());
+            });
+}
+
+/**
  * Test IMapper::get(metadata) with a bad buffer
  */
 TEST_P(GraphicsMapperHidlTest, GetMetadataBadValue) {
@@ -1409,6 +1557,9 @@
     ASSERT_EQ(Error::BAD_BUFFER,
               mGralloc->get(bufferHandle, gralloc4::MetadataType_Smpte2094_40, &vec));
     ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_Smpte2094_10, &vec));
+    ASSERT_EQ(0, vec.size());
 }
 
 /**
@@ -1801,6 +1952,20 @@
 }
 
 /**
+ * Test IMapper::set(Smpte2094_10)
+ */
+TEST_P(GraphicsMapperHidlTest, SetSmpte2094_10) {
+    hidl_vec<uint8_t> vec;
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_10, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                std::optional<std::vector<uint8_t>> realSmpte2094_10;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &realSmpte2094_10));
+                EXPECT_FALSE(realSmpte2094_10.has_value());
+            });
+}
+
+/**
  * Test IMapper::set(metadata) with a bad buffer
  */
 TEST_P(GraphicsMapperHidlTest, SetMetadataNullBuffer) {
@@ -1841,6 +2006,8 @@
     ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
     ASSERT_EQ(Error::BAD_BUFFER,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2094_40, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2094_10, vec));
 }
 
 /**
@@ -2346,6 +2513,24 @@
 }
 
 /**
+ * Test IMapper::getFromBufferDescriptorInfo(Smpte2094_10)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2094_10) {
+    hidl_vec<uint8_t> vec;
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Smpte2094_10, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
+
+    std::optional<std::vector<uint8_t>> smpte2094_10;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &smpte2094_10));
+    EXPECT_FALSE(smpte2094_10.has_value());
+}
+
+/**
  * Test IMapper::getFromBufferDescriptorInfo(metadata) for unsupported metadata
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoUnsupportedMetadata) {
diff --git a/health/1.0/Android.bp b/health/1.0/Android.bp
index 003b106..e793db6 100644
--- a/health/1.0/Android.bp
+++ b/health/1.0/Android.bp
@@ -20,4 +20,8 @@
     ],
     gen_java: true,
     gen_java_constants: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.car.framework",
+    ],
 }
diff --git a/health/2.0/Android.bp b/health/2.0/Android.bp
index ddd983d..fae25b6 100644
--- a/health/2.0/Android.bp
+++ b/health/2.0/Android.bp
@@ -22,4 +22,8 @@
         "android.hidl.base@1.0",
     ],
     gen_java: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.car.framework",
+    ],
 }
diff --git a/input/classifier/1.0/vts/functional/Android.bp b/input/classifier/1.0/vts/functional/Android.bp
index 58945d3..5ff1457 100644
--- a/input/classifier/1.0/vts/functional/Android.bp
+++ b/input/classifier/1.0/vts/functional/Android.bp
@@ -30,7 +30,10 @@
         ":inputconstants_aidl",
         "VtsHalInputClassifierV1_0TargetTest.cpp",
     ],
-    header_libs: ["jni_headers"],
+    header_libs: [
+        "jni_headers",
+        "libbinder_headers",
+    ],
     static_libs: [
         "android.hardware.input.classifier@1.0",
         "android.hardware.input.common@1.0",
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 2449268..7676147 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -3170,6 +3170,49 @@
 }
 
 /*
+ * EncryptionOperationsTest.AesCbcZeroInputSuccessb
+ *
+ * Verifies that keymaster generates correct output on zero-input with
+ * NonePadding mode
+ */
+TEST_P(EncryptionOperationsTest, AesCbcZeroInputSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .AesEncryptionKey(128)
+                                                 .BlockMode(BlockMode::CBC)
+                                                 .Padding(PaddingMode::NONE, PaddingMode::PKCS7)));
+
+    // Zero input message
+    string message = "";
+    for (auto padding : {PaddingMode::NONE, PaddingMode::PKCS7}) {
+        auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(padding);
+        AuthorizationSet out_params;
+        string ciphertext1 = EncryptMessage(message, params, &out_params);
+        HidlBuf iv1 = CopyIv(out_params);
+        if (padding == PaddingMode::NONE)
+            EXPECT_EQ(message.size(), ciphertext1.size()) << "PaddingMode: " << padding;
+        else
+            EXPECT_EQ(message.size(), ciphertext1.size() - 16) << "PaddingMode: " << padding;
+
+        out_params.Clear();
+
+        string ciphertext2 = EncryptMessage(message, params, &out_params);
+        HidlBuf iv2 = CopyIv(out_params);
+        if (padding == PaddingMode::NONE)
+            EXPECT_EQ(message.size(), ciphertext2.size()) << "PaddingMode: " << padding;
+        else
+            EXPECT_EQ(message.size(), ciphertext2.size() - 16) << "PaddingMode: " << padding;
+
+        // IVs should be random
+        EXPECT_NE(iv1, iv2) << "PaddingMode: " << padding;
+
+        params.push_back(TAG_NONCE, iv1);
+        string plaintext = DecryptMessage(ciphertext1, params);
+        EXPECT_EQ(message, plaintext) << "PaddingMode: " << padding;
+    }
+}
+
+/*
  * EncryptionOperationsTest.AesCallerNonce
  *
  * Verifies that AES caller-provided nonces work correctly.
diff --git a/neuralnetworks/aidl/Android.bp b/neuralnetworks/aidl/Android.bp
index 065105a..cbb6ce5 100644
--- a/neuralnetworks/aidl/Android.bp
+++ b/neuralnetworks/aidl/Android.bp
@@ -17,7 +17,7 @@
     stability: "vintf",
     imports: [
         "android.hardware.common-V2",
-        "android.hardware.graphics.common-V2",
+        "android.hardware.graphics.common-V3",
     ],
     backend: {
         java: {
diff --git a/neuralnetworks/aidl/utils/Android.bp b/neuralnetworks/aidl/utils/Android.bp
index 37ad6d6..e356104 100644
--- a/neuralnetworks/aidl/utils/Android.bp
+++ b/neuralnetworks/aidl/utils/Android.bp
@@ -31,7 +31,7 @@
     export_include_dirs: ["include"],
     cflags: ["-Wthread-safety"],
     static_libs: [
-        "android.hardware.graphics.common-V2-ndk",
+        "android.hardware.graphics.common-V3-ndk",
         "libaidlcommonsupport",
         "libarect",
         "neuralnetworks_types",
@@ -78,7 +78,7 @@
     name: "neuralnetworks_use_latest_utils_hal_aidl",
     static_libs: [
         "android.hardware.common-V2-ndk",
-        "android.hardware.graphics.common-V2-ndk",
+        "android.hardware.graphics.common-V3-ndk",
         "android.hardware.neuralnetworks-V3-ndk",
         "neuralnetworks_utils_hal_aidl",
     ],
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
index 8920c01..ba444a7 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
@@ -49,4 +49,5 @@
   CAMERA_STREAMING_LOW = 12,
   CAMERA_STREAMING_MID = 13,
   CAMERA_STREAMING_HIGH = 14,
+  GAME_LOADING = 15,
 }
diff --git a/power/aidl/android/hardware/power/Mode.aidl b/power/aidl/android/hardware/power/Mode.aidl
index ae113e3..2ebace1 100644
--- a/power/aidl/android/hardware/power/Mode.aidl
+++ b/power/aidl/android/hardware/power/Mode.aidl
@@ -162,4 +162,9 @@
      * This hint indicates that camera high resolution stream is being started.
      */
     CAMERA_STREAMING_HIGH,
+
+    /**
+     * This mode indicates that the user is waiting for loading in a game.
+     */
+    GAME_LOADING,
 }
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index 9acb9e0..223b9d5 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -30,7 +30,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.power-V2-ndk",
+        "android.hardware.power-V3-ndk",
     ],
     srcs: [
         "main.cpp",
diff --git a/power/aidl/default/power-default.xml b/power/aidl/default/power-default.xml
index 9f56deb..927ba22 100644
--- a/power/aidl/default/power-default.xml
+++ b/power/aidl/default/power-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.power</name>
-        <version>2</version>
+        <version>3</version>
         <fqname>IPower/default</fqname>
     </hal>
 </manifest>
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
index 16433be..c618791 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
@@ -68,4 +68,6 @@
   oneway void startNetworkScan(in int serial, in android.hardware.radio.network.NetworkScanRequest request);
   oneway void stopNetworkScan(in int serial);
   oneway void supplyNetworkDepersonalization(in int serial, in String netPin);
+  oneway void setUsageSetting(in int serial, in android.hardware.radio.network.UsageSetting usageSetting);
+  oneway void getUsageSetting(in int serial);
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
index ff95396..8cf4c31 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -67,4 +67,6 @@
   oneway void startNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
   oneway void stopNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
   oneway void supplyNetworkDepersonalizationResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
+  oneway void setUsageSettingResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void getUsageSettingResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.UsageSetting usageSetting);
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
new file mode 100644
index 0000000..7fdf831
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @VintfStability
+enum UsageSetting {
+  VOICE_CENTRIC = 1,
+  DATA_CENTRIC = 2,
+}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index 1081a75..aaf432a 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -27,6 +27,7 @@
 import android.hardware.radio.network.RadioAccessSpecifier;
 import android.hardware.radio.network.RadioBandMode;
 import android.hardware.radio.network.SignalThresholdInfo;
+import android.hardware.radio.network.UsageSetting;
 
 /**
  * This interface is used by telephony and telecom to talk to cellular radio for network APIs.
@@ -416,4 +417,25 @@
      * Response function is IRadioNetworkResponse.supplyNetworkDepersonalizationResponse()
      */
     void supplyNetworkDepersonalization(in int serial, in String netPin);
+
+    /**
+     * Set the UE usage setting for data/voice centric usage.
+     *
+     * <p>Sets the usage setting in accordance with 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+     * <p>This value must be independently preserved for each SIM; (setting the value is not a
+     * "global" override).
+     *
+     * @param serial Serial number of request.
+     * @param usageSetting the usage setting for the current SIM.
+     */
+    oneway void setUsageSetting(in int serial, in UsageSetting usageSetting);
+
+    /**
+     * Get the UE usage setting for data/voice centric usage.
+     *
+     * <p>Gets the usage setting in accordance with 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+     *
+     * @param serial Serial number of request.
+     */
+    oneway void getUsageSetting(in int serial);
 }
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 429b5a8..30f4221 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -31,6 +31,7 @@
 import android.hardware.radio.network.RadioBandMode;
 import android.hardware.radio.network.RegStateResult;
 import android.hardware.radio.network.SignalStrength;
+import android.hardware.radio.network.UsageSetting;
 
 /**
  * Interface declaring response functions to solicited radio requests for network APIs.
@@ -549,4 +550,30 @@
      *   RadioError:SIM_ABSENT
      */
     void supplyNetworkDepersonalizationResponse(in RadioResponseInfo info, in int remainingRetries);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_STATE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SIM_ABSENT
+     */
+    oneway void setUsageSettingResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error.
+     * @param usageSetting the usage setting for the current SIM.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_STATE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SIM_ABSENT
+     */
+    oneway void getUsageSettingResponse(in RadioResponseInfo info, in UsageSetting usageSetting);
 }
diff --git a/radio/aidl/android/hardware/radio/network/UsageSetting.aidl b/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
new file mode 100644
index 0000000..ba8fe93
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * Cellular usage setting with values according to 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+ *
+ * <p>Also refer to "UE's usage setting" as defined in 3gpp 24.301 section 3.1 and 3gpp 23.221
+ * Annex A.
+ */
+@VintfStability
+@Backing(type="int")
+enum UsageSetting {
+    /**
+     * UE operates in voice-centric mode. Generally speaking, in this mode of operation, the UE
+     * will not remain camped on a cell or attached to a network unless that cell/network provides
+     * voice service.
+     */
+    VOICE_CENTRIC = 1,
+
+    /**
+     * UE operates in data-centric mode. Generally speaking, in this mode of operation, the UE
+     * will not reselect away from a cell/network that only provides data services.
+     */
+    DATA_CENTRIC = 2,
+}
diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp
index 5294de4..487d91b 100644
--- a/radio/aidl/compat/libradiocompat/Android.bp
+++ b/radio/aidl/compat/libradiocompat/Android.bp
@@ -28,7 +28,6 @@
     cflags: [
         "-Wall",
         "-Wextra",
-        //"-Wold-style-cast",  // TODO(b/203699028) enable after aosp/1900880 gets merged
         "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
     shared_libs: [
@@ -56,6 +55,7 @@
         "libutils",
     ],
     srcs: [
+        "CallbackManager.cpp",
         "DriverContext.cpp",
         "RadioCompatBase.cpp",
         "RadioIndication.cpp",
diff --git a/radio/aidl/compat/libradiocompat/CallbackManager.cpp b/radio/aidl/compat/libradiocompat/CallbackManager.cpp
new file mode 100644
index 0000000..c2eaed1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/CallbackManager.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/CallbackManager.h>
+
+#include <android-base/logging.h>
+
+using namespace std::literals::chrono_literals;
+
+namespace android::hardware::radio::compat {
+
+/**
+ * How much setter thread will wait with setting response functions after the last
+ * setResponseFunctions call from the framework. Subsequent calls from the framework reset the
+ * clock, so this number should be larger than the longest time between setResponseFunctions calls
+ * from the framework.
+ *
+ * Real world measurements with Cuttlefish give <10ms delay between Modem and Data and <2ms delays
+ * between all others.
+ */
+static constexpr auto kDelayedSetterDelay = 100ms;
+
+CallbackManager::CallbackManager(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal)
+    : mHidlHal(hidlHal),
+      mRadioResponse(sp<compat::RadioResponse>::make(context)),
+      mRadioIndication(sp<compat::RadioIndication>::make(context)),
+      mDelayedSetterThread(&CallbackManager::delayedSetterThread, this) {}
+
+CallbackManager::~CallbackManager() {
+    {
+        std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+        mDelayedSetterDeadline = std::nullopt;
+        mDestroy = true;
+        mDelayedSetterCv.notify_all();
+    }
+    mDelayedSetterThread.join();
+}
+
+RadioResponse& CallbackManager::response() const {
+    return *mRadioResponse;
+}
+
+void CallbackManager::setResponseFunctionsDelayed() {
+    std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+    mDelayedSetterDeadline = std::chrono::steady_clock::now() + kDelayedSetterDelay;
+    mDelayedSetterCv.notify_all();
+}
+
+void CallbackManager::delayedSetterThread() {
+    while (!mDestroy) {
+        std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+        auto deadline = mDelayedSetterDeadline;
+
+        // not waiting to set response functions
+        if (!deadline) {
+            mDelayedSetterCv.wait(lock);
+            continue;
+        }
+
+        // waiting to set response functions, but not yet
+        if (*deadline > std::chrono::steady_clock::now()) {
+            mDelayedSetterCv.wait_until(lock, *deadline);
+            continue;
+        }
+
+        mHidlHal->setResponseFunctions(mRadioResponse, mRadioIndication).assertOk();
+        mDelayedSetterDeadline = std::nullopt;
+    }
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp b/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp
index dba6c19..2a2d7a3 100644
--- a/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp
+++ b/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp
@@ -21,16 +21,10 @@
 namespace android::hardware::radio::compat {
 
 RadioCompatBase::RadioCompatBase(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal,
-                                 sp<RadioResponse> radioResponse, sp<RadioIndication> radioInd)
+                                 std::shared_ptr<CallbackManager> cbMgr)
     : mContext(context),
       mHal1_5(hidlHal),
       mHal1_6(V1_6::IRadio::castFrom(hidlHal)),
-      mRadioResponse(radioResponse),
-      mRadioIndication(radioInd) {}
-
-V1_6::IRadioResponse& RadioCompatBase::respond() {
-    CHECK(mRadioResponse) << "This shouldn't happen (response functions are passed in constructor)";
-    return *mRadioResponse;
-}
+      mCallbackManager(cbMgr) {}
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/RadioResponse.cpp b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
index e1bd446..dbeb68a 100644
--- a/radio/aidl/compat/libradiocompat/RadioResponse.cpp
+++ b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
@@ -27,12 +27,12 @@
 Return<void> RadioResponse::acknowledgeRequest(int32_t serial) {
     LOG_CALL << serial;
     // TODO(b/203699028): send to correct requestor or confirm if spam is not a problem
-    if (mDataCb) mDataCb->acknowledgeRequest(serial);
-    if (mMessagingCb) mMessagingCb->acknowledgeRequest(serial);
-    if (mModemCb) mModemCb->acknowledgeRequest(serial);
-    if (mNetworkCb) mNetworkCb->acknowledgeRequest(serial);
-    if (mSimCb) mSimCb->acknowledgeRequest(serial);
-    if (mVoiceCb) mVoiceCb->acknowledgeRequest(serial);
+    if (mDataCb) mDataCb.get()->acknowledgeRequest(serial);
+    if (mMessagingCb) mMessagingCb.get()->acknowledgeRequest(serial);
+    if (mModemCb) mModemCb.get()->acknowledgeRequest(serial);
+    if (mNetworkCb) mNetworkCb.get()->acknowledgeRequest(serial);
+    if (mSimCb) mSimCb.get()->acknowledgeRequest(serial);
+    if (mVoiceCb) mVoiceCb.get()->acknowledgeRequest(serial);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/commonStructs.cpp b/radio/aidl/compat/libradiocompat/commonStructs.cpp
index c25768d..6e4c873 100644
--- a/radio/aidl/compat/libradiocompat/commonStructs.cpp
+++ b/radio/aidl/compat/libradiocompat/commonStructs.cpp
@@ -20,11 +20,11 @@
 
 namespace aidl = ::aidl::android::hardware::radio;
 
-V1_6::RadioResponseInfo notSupported(int32_t serial) {
+aidl::RadioResponseInfo notSupported(int32_t serial) {
     return {
-            .type = V1_0::RadioResponseType::SOLICITED,
+            .type = aidl::RadioResponseType::SOLICITED,
             .serial = serial,
-            .error = V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+            .error = aidl::RadioError::REQUEST_NOT_SUPPORTED,
     };
 }
 
diff --git a/radio/aidl/compat/libradiocompat/commonStructs.h b/radio/aidl/compat/libradiocompat/commonStructs.h
index b859916..a4a4869 100644
--- a/radio/aidl/compat/libradiocompat/commonStructs.h
+++ b/radio/aidl/compat/libradiocompat/commonStructs.h
@@ -21,7 +21,7 @@
 
 namespace android::hardware::radio::compat {
 
-V1_6::RadioResponseInfo notSupported(int32_t serial);
+aidl::android::hardware::radio::RadioResponseInfo notSupported(int32_t serial);
 
 std::string toAidl(const hidl_string& str);
 hidl_string toHidl(const std::string& str);
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
index d0d6f7a..5b22dbe 100644
--- a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
@@ -16,8 +16,6 @@
 
 #include <libradiocompat/RadioConfig.h>
 
-#include "RadioConfigIndication.h"
-#include "RadioConfigResponse.h"
 #include "commonStructs.h"
 #include "debug.h"
 #include "structs.h"
@@ -31,11 +29,13 @@
 constexpr auto ok = &ScopedAStatus::ok;
 
 RadioConfig::RadioConfig(sp<config::V1_1::IRadioConfig> hidlHal)
-    : mHal1_1(hidlHal), mHal1_3(config::V1_3::IRadioConfig::castFrom(hidlHal)) {}
+    : mHal1_1(hidlHal),
+      mHal1_3(config::V1_3::IRadioConfig::castFrom(hidlHal)),
+      mRadioConfigResponse(sp<RadioConfigResponse>::make()),
+      mRadioConfigIndication(sp<RadioConfigIndication>::make()) {}
 
-config::V1_3::IRadioConfigResponse& RadioConfig::respond() {
-    CHECK(mRadioConfigResponse) << "setResponseFunctions was not called yet";
-    return *mRadioConfigResponse;
+std::shared_ptr<aidl::IRadioConfigResponse> RadioConfig::respond() {
+    return mRadioConfigResponse->respond();
 }
 
 ScopedAStatus RadioConfig::getHalDeviceCapabilities(int32_t serial) {
@@ -43,7 +43,7 @@
     if (mHal1_3) {
         mHal1_3->getHalDeviceCapabilities(serial);
     } else {
-        respond().getHalDeviceCapabilitiesResponse(notSupported(serial), false);
+        respond()->getHalDeviceCapabilitiesResponse(notSupported(serial), false);
     }
     return ok();
 }
@@ -86,9 +86,9 @@
     CHECK(radioConfigResponse);
     CHECK(radioConfigIndication);
 
-    mRadioConfigResponse = sp<RadioConfigResponse>::make(radioConfigResponse);
-    mRadioConfigIndication = sp<RadioConfigIndication>::make(radioConfigIndication);
-    mHal1_1->setResponseFunctions(mRadioConfigResponse, mRadioConfigIndication);
+    mRadioConfigResponse->setResponseFunction(radioConfigResponse);
+    mRadioConfigIndication->setResponseFunction(radioConfigIndication);
+    mHal1_1->setResponseFunctions(mRadioConfigResponse, mRadioConfigIndication).assertOk();
 
     return ok();
 }
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp
index 0320ad7..c1e32c1 100644
--- a/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "RadioConfigIndication.h"
+#include <libradiocompat/RadioConfigIndication.h>
 
 #include "commonStructs.h"
 #include "debug.h"
@@ -28,20 +28,26 @@
 
 namespace aidl = ::aidl::android::hardware::radio::config;
 
-RadioConfigIndication::RadioConfigIndication(std::shared_ptr<aidl::IRadioConfigIndication> callback)
-    : mCallback(callback) {}
+void RadioConfigIndication::setResponseFunction(
+        std::shared_ptr<aidl::IRadioConfigIndication> callback) {
+    mCallback = callback;
+}
+
+std::shared_ptr<aidl::IRadioConfigIndication> RadioConfigIndication::indicate() {
+    return mCallback.get();
+}
 
 Return<void> RadioConfigIndication::simSlotsStatusChanged(
         V1_0::RadioIndicationType type, const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) {
     LOG_CALL << type;
-    mCallback->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
+    indicate()->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
     return {};
 }
 
 Return<void> RadioConfigIndication::simSlotsStatusChanged_1_2(
         V1_0::RadioIndicationType type, const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) {
     LOG_CALL << type;
-    mCallback->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
+    indicate()->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.h b/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.h
deleted file mode 100644
index 3d8d971..0000000
--- a/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <aidl/android/hardware/radio/config/IRadioConfigIndication.h>
-#include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
-
-namespace android::hardware::radio::compat {
-
-class RadioConfigIndication : public config::V1_2::IRadioConfigIndication {
-    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication> mCallback;
-
-    Return<void> simSlotsStatusChanged(
-            V1_0::RadioIndicationType type,
-            const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) override;
-    Return<void> simSlotsStatusChanged_1_2(
-            V1_0::RadioIndicationType type,
-            const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) override;
-
-  public:
-    RadioConfigIndication(
-            std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication> cb);
-};
-
-}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp
index 7066ae4..523c504 100644
--- a/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "RadioConfigResponse.h"
+#include <libradiocompat/RadioConfigResponse.h>
 
 #include "commonStructs.h"
 #include "debug.h"
@@ -28,14 +28,20 @@
 
 namespace aidl = ::aidl::android::hardware::radio::config;
 
-RadioConfigResponse::RadioConfigResponse(std::shared_ptr<aidl::IRadioConfigResponse> callback)
-    : mCallback(callback) {}
+void RadioConfigResponse::setResponseFunction(
+        std::shared_ptr<aidl::IRadioConfigResponse> callback) {
+    mCallback = callback;
+}
+
+std::shared_ptr<aidl::IRadioConfigResponse> RadioConfigResponse::respond() {
+    return mCallback.get();
+}
 
 Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
         const V1_0::RadioResponseInfo& info,
         const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) {
     LOG_CALL << info.serial;
-    mCallback->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
+    respond()->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
     return {};
 };
 
@@ -43,47 +49,47 @@
         const V1_0::RadioResponseInfo& info,
         const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) {
     LOG_CALL << info.serial;
-    mCallback->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
+    respond()->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
     return {};
 };
 
 Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    mCallback->setSimSlotsMappingResponse(toAidl(info));
+    respond()->setSimSlotsMappingResponse(toAidl(info));
     return {};
 };
 
 Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
         const V1_0::RadioResponseInfo& info, const config::V1_1::PhoneCapability& phoneCapability) {
     LOG_CALL << info.serial;
-    mCallback->getPhoneCapabilityResponse(toAidl(info), toAidl(phoneCapability));
+    respond()->getPhoneCapabilityResponse(toAidl(info), toAidl(phoneCapability));
     return {};
 };
 
 Return<void> RadioConfigResponse::setPreferredDataModemResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    mCallback->setPreferredDataModemResponse(toAidl(info));
+    respond()->setPreferredDataModemResponse(toAidl(info));
     return {};
 };
 
 Return<void> RadioConfigResponse::setModemsConfigResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    mCallback->setNumOfLiveModemsResponse(toAidl(info));
+    respond()->setNumOfLiveModemsResponse(toAidl(info));
     return {};
 };
 
 Return<void> RadioConfigResponse::getModemsConfigResponse(
         const V1_0::RadioResponseInfo& info, const config::V1_1::ModemsConfig& modemsConfig) {
     LOG_CALL << info.serial;
-    mCallback->getNumOfLiveModemsResponse(toAidl(info), modemsConfig.numOfLiveModems);
+    respond()->getNumOfLiveModemsResponse(toAidl(info), modemsConfig.numOfLiveModems);
     return {};
 };
 
 Return<void> RadioConfigResponse::getHalDeviceCapabilitiesResponse(
         const V1_6::RadioResponseInfo& info, bool modemReducedFeatureSet1) {
     LOG_CALL << info.serial;
-    mCallback->getHalDeviceCapabilitiesResponse(toAidl(info), modemReducedFeatureSet1);
+    respond()->getHalDeviceCapabilitiesResponse(toAidl(info), modemReducedFeatureSet1);
     return {};
 };
 
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.h b/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.h
deleted file mode 100644
index 1461dd2..0000000
--- a/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <aidl/android/hardware/radio/config/IRadioConfigResponse.h>
-#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
-
-namespace android::hardware::radio::compat {
-
-class RadioConfigResponse : public config::V1_3::IRadioConfigResponse {
-    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse> mCallback;
-
-    Return<void> getSimSlotsStatusResponse(
-            const V1_0::RadioResponseInfo& info,
-            const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) override;
-    Return<void> setSimSlotsMappingResponse(const V1_0::RadioResponseInfo& info) override;
-    Return<void> getPhoneCapabilityResponse(
-            const V1_0::RadioResponseInfo& info,
-            const config::V1_1::PhoneCapability& phoneCapability) override;
-    Return<void> setPreferredDataModemResponse(const V1_0::RadioResponseInfo& info) override;
-    Return<void> setModemsConfigResponse(const V1_0::RadioResponseInfo& info) override;
-    Return<void> getModemsConfigResponse(const V1_0::RadioResponseInfo& info,
-                                         const config::V1_1::ModemsConfig& modemsConfig) override;
-    Return<void> getSimSlotsStatusResponse_1_2(
-            const V1_0::RadioResponseInfo& info,
-            const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) override;
-    Return<void> getHalDeviceCapabilitiesResponse(const V1_6::RadioResponseInfo& info,
-                                                  bool modemReducedFeatureSet1) override;
-
-  public:
-    RadioConfigResponse(
-            std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse> callback);
-};
-
-}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/data/RadioData.cpp b/radio/aidl/compat/libradiocompat/data/RadioData.cpp
index cc6f526..d2f3687 100644
--- a/radio/aidl/compat/libradiocompat/data/RadioData.cpp
+++ b/radio/aidl/compat/libradiocompat/data/RadioData.cpp
@@ -31,12 +31,16 @@
 namespace aidlCommon = ::aidl::android::hardware::radio;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioDataResponse> RadioData::respond() {
+    return mCallbackManager->response().dataCb();
+}
+
 ScopedAStatus RadioData::allocatePduSessionId(int32_t serial) {
     LOG_CALL << serial;
     if (mHal1_6) {
         mHal1_6->allocatePduSessionId(serial);
     } else {
-        respond().allocatePduSessionIdResponse(notSupported(serial), 0);
+        respond()->allocatePduSessionIdResponse(notSupported(serial), 0);
     }
     return ok();
 }
@@ -46,7 +50,7 @@
     if (mHal1_6) {
         mHal1_6->cancelHandover(serial, callId);
     } else {
-        respond().cancelHandoverResponse(notSupported(serial));
+        respond()->cancelHandoverResponse(notSupported(serial));
     }
     return ok();
 }
@@ -60,7 +64,11 @@
 
 ScopedAStatus RadioData::getDataCallList(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getDataCallList(serial);
+    if (mHal1_6) {
+        mHal1_6->getDataCallList_1_6(serial);
+    } else {
+        mHal1_5->getDataCallList(serial);
+    }
     return ok();
 }
 
@@ -69,7 +77,7 @@
     if (mHal1_6) {
         mHal1_6->getSlicingConfig(serial);
     } else {
-        respond().getSlicingConfigResponse(notSupported(serial), {});
+        respond()->getSlicingConfigResponse(notSupported(serial), {});
     }
     return ok();
 }
@@ -79,7 +87,7 @@
     if (mHal1_6) {
         mHal1_6->releasePduSessionId(serial, id);
     } else {
-        respond().releasePduSessionIdResponse(notSupported(serial));
+        respond()->releasePduSessionIdResponse(notSupported(serial));
     }
     return ok();
 }
@@ -109,7 +117,7 @@
     if (mHal1_6) {
         mHal1_6->setDataThrottling(serial, V1_6::DataThrottlingAction(dta), completionDurationMs);
     } else {
-        respond().setDataThrottlingResponse(notSupported(serial));
+        respond()->setDataThrottlingResponse(notSupported(serial));
     }
     return ok();
 }
@@ -121,16 +129,10 @@
 }
 
 ScopedAStatus RadioData::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioDataResponse>& dataResponse,
-        const std::shared_ptr<aidl::IRadioDataIndication>& dataIndication) {
-    LOG_CALL << dataResponse << ' ' << dataIndication;
-
-    CHECK(dataResponse);
-    CHECK(dataIndication);
-
-    mRadioResponse->setResponseFunction(dataResponse);
-    mRadioIndication->setResponseFunction(dataIndication);
-
+        const std::shared_ptr<aidl::IRadioDataResponse>& response,
+        const std::shared_ptr<aidl::IRadioDataIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
@@ -161,7 +163,7 @@
     if (mHal1_6) {
         mHal1_6->startHandover(serial, callId);
     } else {
-        respond().startHandoverResponse(notSupported(serial));
+        respond()->startHandoverResponse(notSupported(serial));
     }
     return ok();
 }
diff --git a/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp b/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
index a680e56..1d367d2 100644
--- a/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
+++ b/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
@@ -29,10 +29,13 @@
 namespace aidl = ::aidl::android::hardware::radio::data;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioDataIndication> dataCb) {
-    CHECK(dataCb);
     mDataCb = dataCb;
 }
 
+std::shared_ptr<aidl::IRadioDataIndication> RadioIndication::dataCb() {
+    return mDataCb.get();
+}
+
 Return<void> RadioIndication::dataCallListChanged(V1_0::RadioIndicationType type,
                                                   const hidl_vec<V1_0::SetupDataCallResult>&) {
     LOG_CALL << type;
@@ -50,40 +53,35 @@
 Return<void> RadioIndication::dataCallListChanged_1_5(
         V1_0::RadioIndicationType type, const hidl_vec<V1_5::SetupDataCallResult>& dcList) {
     LOG_CALL << type;
-    CHECK_CB(mDataCb);
-    mDataCb->dataCallListChanged(toAidl(type), toAidl(dcList));
+    dataCb()->dataCallListChanged(toAidl(type), toAidl(dcList));
     return {};
 }
 
 Return<void> RadioIndication::dataCallListChanged_1_6(
         V1_0::RadioIndicationType type, const hidl_vec<V1_6::SetupDataCallResult>& dcList) {
     LOG_CALL << type;
-    CHECK_CB(mDataCb);
-    mDataCb->dataCallListChanged(toAidl(type), toAidl(dcList));
+    dataCb()->dataCallListChanged(toAidl(type), toAidl(dcList));
     return {};
 }
 
 Return<void> RadioIndication::keepaliveStatus(V1_0::RadioIndicationType type,
                                               const V1_1::KeepaliveStatus& status) {
     LOG_CALL << type;
-    CHECK_CB(mDataCb);
-    mDataCb->keepaliveStatus(toAidl(type), toAidl(status));
+    dataCb()->keepaliveStatus(toAidl(type), toAidl(status));
     return {};
 }
 
 Return<void> RadioIndication::pcoData(V1_0::RadioIndicationType type,
                                       const V1_0::PcoDataInfo& pco) {
     LOG_CALL << type;
-    CHECK_CB(mDataCb);
-    mDataCb->pcoData(toAidl(type), toAidl(pco));
+    dataCb()->pcoData(toAidl(type), toAidl(pco));
     return {};
 }
 
 Return<void> RadioIndication::unthrottleApn(V1_0::RadioIndicationType type,
                                             const hidl_string& apn) {
     LOG_CALL << type;
-    CHECK_CB(mDataCb);
-    mDataCb->unthrottleApn(toAidl(type), mContext->getDataProfile(apn));
+    dataCb()->unthrottleApn(toAidl(type), mContext->getDataProfile(apn));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp b/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp
index 171f692..0bfa2df 100644
--- a/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp
+++ b/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp
@@ -29,29 +29,29 @@
 namespace aidl = ::aidl::android::hardware::radio::data;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioDataResponse> dataCb) {
-    CHECK(dataCb);
     mDataCb = dataCb;
 }
 
+std::shared_ptr<aidl::IRadioDataResponse> RadioResponse::dataCb() {
+    return mDataCb.get();
+}
+
 Return<void> RadioResponse::allocatePduSessionIdResponse(const V1_6::RadioResponseInfo& info,
                                                          int32_t id) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->allocatePduSessionIdResponse(toAidl(info), id);
+    dataCb()->allocatePduSessionIdResponse(toAidl(info), id);
     return {};
 }
 
 Return<void> RadioResponse::cancelHandoverResponse(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->cancelHandoverResponse(toAidl(info));
+    dataCb()->cancelHandoverResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::deactivateDataCallResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->deactivateDataCallResponse(toAidl(info));
+    dataCb()->deactivateDataCallResponse(toAidl(info));
     return {};
 }
 
@@ -73,8 +73,7 @@
         const V1_0::RadioResponseInfo& info,
         const hidl_vec<V1_5::SetupDataCallResult>& dcResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
+    dataCb()->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
     return {};
 }
 
@@ -82,65 +81,56 @@
         const V1_6::RadioResponseInfo& info,
         const hidl_vec<V1_6::SetupDataCallResult>& dcResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
+    dataCb()->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
     return {};
 }
 
 Return<void> RadioResponse::getSlicingConfigResponse(const V1_6::RadioResponseInfo& info,
                                                      const V1_6::SlicingConfig& slicingConfig) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->getSlicingConfigResponse(toAidl(info), toAidl(slicingConfig));
+    dataCb()->getSlicingConfigResponse(toAidl(info), toAidl(slicingConfig));
     return {};
 }
 
 Return<void> RadioResponse::releasePduSessionIdResponse(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->releasePduSessionIdResponse(toAidl(info));
+    dataCb()->releasePduSessionIdResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setDataAllowedResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setDataAllowedResponse(toAidl(info));
+    dataCb()->setDataAllowedResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setDataProfileResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setDataProfileResponse(toAidl(info));
+    dataCb()->setDataProfileResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setDataProfileResponse_1_5(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setDataProfileResponse(toAidl(info));
+    dataCb()->setDataProfileResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setDataThrottlingResponse(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setDataThrottlingResponse(toAidl(info));
+    dataCb()->setDataThrottlingResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setInitialAttachApnResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setInitialAttachApnResponse(toAidl(info));
+    dataCb()->setInitialAttachApnResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setInitialAttachApnResponse_1_5(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setInitialAttachApnResponse(toAidl(info));
+    dataCb()->setInitialAttachApnResponse(toAidl(info));
     return {};
 }
 
@@ -161,38 +151,33 @@
 Return<void> RadioResponse::setupDataCallResponse_1_5(const V1_0::RadioResponseInfo& info,
                                                       const V1_5::SetupDataCallResult& dcResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
+    dataCb()->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
     return {};
 }
 
 Return<void> RadioResponse::setupDataCallResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                       const V1_6::SetupDataCallResult& dcResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
+    dataCb()->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
     return {};
 }
 
 Return<void> RadioResponse::startHandoverResponse(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->startHandoverResponse(toAidl(info));
+    dataCb()->startHandoverResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::startKeepaliveResponse(const V1_0::RadioResponseInfo& info,
                                                    const V1_1::KeepaliveStatus& status) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->startKeepaliveResponse(toAidl(info), toAidl(status));
+    dataCb()->startKeepaliveResponse(toAidl(info), toAidl(status));
     return {};
 }
 
 Return<void> RadioResponse::stopKeepaliveResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->stopKeepaliveResponse(toAidl(info));
+    dataCb()->stopKeepaliveResponse(toAidl(info));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/debug.h b/radio/aidl/compat/libradiocompat/debug.h
index 4158059..cb773bf 100644
--- a/radio/aidl/compat/libradiocompat/debug.h
+++ b/radio/aidl/compat/libradiocompat/debug.h
@@ -26,12 +26,6 @@
 #define LOG_CALL \
     if constexpr (debug::kSuperVerbose) LOG(VERBOSE) << (RADIO_MODULE ".") << __func__ << ' '
 
-#define CHECK_CB(field)                     \
-    if (!field) {                           \
-        LOG(WARNING) << "Callback not set"; \
-        return {};                          \
-    }
-
 }  // namespace debug
 
 inline std::ostream& operator<<(std::ostream& os, const V1_0::RadioIndicationType& type) {
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h
new file mode 100644
index 0000000..f1a7b49
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "DriverContext.h"
+#include "RadioIndication.h"
+#include "RadioResponse.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/radio/1.6/IRadio.h>
+
+#include <thread>
+
+namespace android::hardware::radio::compat {
+
+class CallbackManager {
+    sp<V1_5::IRadio> mHidlHal;
+    sp<RadioResponse> mRadioResponse;
+    sp<RadioIndication> mRadioIndication;
+
+    std::thread mDelayedSetterThread;
+    std::mutex mDelayedSetterGuard;
+    std::optional<std::chrono::time_point<std::chrono::steady_clock>> mDelayedSetterDeadline
+            GUARDED_BY(mDelayedSetterGuard);
+    std::condition_variable mDelayedSetterCv GUARDED_BY(mDelayedSetterGuard);
+    bool mDestroy GUARDED_BY(mDelayedSetterGuard) = false;
+
+    void setResponseFunctionsDelayed();
+    void delayedSetterThread();
+
+  public:
+    CallbackManager(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal);
+    ~CallbackManager();
+
+    RadioResponse& response() const;
+
+    template <typename ResponseType, typename IndicationType>
+    void setResponseFunctions(const std::shared_ptr<ResponseType>& response,
+                              const std::shared_ptr<IndicationType>& indication) {
+        CHECK(response);
+        CHECK(indication);
+
+        mRadioResponse->setResponseFunction(response);
+        mRadioIndication->setResponseFunction(indication);
+        setResponseFunctionsDelayed();
+    }
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h
new file mode 100644
index 0000000..0b6ee11
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android-base/logging.h>
+#include <android/binder_interface_utils.h>
+#include <utils/Mutex.h>
+
+namespace android::hardware::radio::compat {
+
+template <typename Interface, typename DefaultImplementation, bool isIndication = false>
+class GuaranteedCallback {
+    mutable std::mutex mCallbackGuard;
+    std::shared_ptr<Interface> mCallback GUARDED_BY(mCallbackGuard);
+
+  public:
+    GuaranteedCallback<Interface, DefaultImplementation, isIndication>& operator=(
+            const std::shared_ptr<Interface>& callback) {
+        CHECK(callback);
+        const std::lock_guard<std::mutex> lock(mCallbackGuard);
+        mCallback = callback;
+        return *this;
+    }
+
+    std::shared_ptr<Interface> get() {
+        if (mCallback) return mCallback;
+        const std::lock_guard<std::mutex> lock(mCallbackGuard);
+        if (mCallback) return mCallback;
+
+        LOG(isIndication ? WARNING : ERROR) << "Callback is not set";
+        return mCallback = ndk::SharedRefBase::make<DefaultImplementation>();
+    }
+
+    operator bool() const { return mCallback != nullptr; }
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h
index 21d7898..eb22fff 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h
@@ -15,9 +15,8 @@
  */
 #pragma once
 
+#include "CallbackManager.h"
 #include "DriverContext.h"
-#include "RadioIndication.h"
-#include "RadioResponse.h"
 
 #include <android/hardware/radio/1.6/IRadio.h>
 
@@ -30,14 +29,11 @@
     sp<V1_5::IRadio> mHal1_5;
     sp<V1_6::IRadio> mHal1_6;
 
-    sp<RadioResponse> mRadioResponse;
-    sp<RadioIndication> mRadioIndication;
-
-    V1_6::IRadioResponse& respond();
+    std::shared_ptr<CallbackManager> mCallbackManager;
 
   public:
     RadioCompatBase(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal,
-                    sp<RadioResponse> radioResponse, sp<RadioIndication> radioIndication);
+                    std::shared_ptr<CallbackManager> cbMgr);
 };
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
index 31ad207..bbfff61 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
@@ -15,6 +15,9 @@
  */
 #pragma once
 
+#include "RadioConfigIndication.h"
+#include "RadioConfigResponse.h"
+
 #include <aidl/android/hardware/radio/config/BnRadioConfig.h>
 #include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
 #include <android/hardware/radio/config/1.3/IRadioConfig.h>
@@ -30,11 +33,13 @@
  * fetch source implementation and publish resulting HAL instance.
  */
 class RadioConfig : public aidl::android::hardware::radio::config::BnRadioConfig {
-    sp<config::V1_1::IRadioConfig> mHal1_1;
-    sp<config::V1_3::IRadioConfig> mHal1_3;
+    const sp<config::V1_1::IRadioConfig> mHal1_1;
+    const sp<config::V1_3::IRadioConfig> mHal1_3;
 
-    sp<config::V1_3::IRadioConfigResponse> mRadioConfigResponse;
-    sp<config::V1_2::IRadioConfigIndication> mRadioConfigIndication;
+    const sp<RadioConfigResponse> mRadioConfigResponse;
+    const sp<RadioConfigIndication> mRadioConfigIndication;
+
+    std::shared_ptr<::aidl::android::hardware::radio::config::IRadioConfigResponse> respond();
 
     ::ndk::ScopedAStatus getHalDeviceCapabilities(int32_t serial) override;
     ::ndk::ScopedAStatus getNumOfLiveModems(int32_t serial) override;
@@ -52,8 +57,6 @@
             const std::vector<aidl::android::hardware::radio::config::SlotPortMapping>& slotMap)
             override;
 
-    config::V1_3::IRadioConfigResponse& respond();
-
   public:
     /**
      * Constructs AIDL IRadioConfig instance wrapping existing HIDL IRadioConfig instance.
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h
new file mode 100644
index 0000000..d256a87
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "GuaranteedCallback.h"
+
+#include <aidl/android/hardware/radio/config/IRadioConfigIndication.h>
+#include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioConfigIndication : public config::V1_2::IRadioConfigIndication {
+    GuaranteedCallback<aidl::android::hardware::radio::config::IRadioConfigIndication,
+                       aidl::android::hardware::radio::config::IRadioConfigIndicationDefault, true>
+            mCallback;
+
+    Return<void> simSlotsStatusChanged(
+            V1_0::RadioIndicationType type,
+            const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) override;
+    Return<void> simSlotsStatusChanged_1_2(
+            V1_0::RadioIndicationType type,
+            const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) override;
+
+  public:
+    void setResponseFunction(
+            std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication> cb);
+
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication> indicate();
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h
new file mode 100644
index 0000000..dc86da2
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "GuaranteedCallback.h"
+
+#include <aidl/android/hardware/radio/config/IRadioConfigResponse.h>
+#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioConfigResponse : public config::V1_3::IRadioConfigResponse {
+    GuaranteedCallback<aidl::android::hardware::radio::config::IRadioConfigResponse,
+                       aidl::android::hardware::radio::config::IRadioConfigResponseDefault>
+            mCallback;
+
+    Return<void> getSimSlotsStatusResponse(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) override;
+    Return<void> setSimSlotsMappingResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getPhoneCapabilityResponse(
+            const V1_0::RadioResponseInfo& info,
+            const config::V1_1::PhoneCapability& phoneCapability) override;
+    Return<void> setPreferredDataModemResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setModemsConfigResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getModemsConfigResponse(const V1_0::RadioResponseInfo& info,
+                                         const config::V1_1::ModemsConfig& modemsConfig) override;
+    Return<void> getSimSlotsStatusResponse_1_2(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) override;
+    Return<void> getHalDeviceCapabilitiesResponse(const V1_6::RadioResponseInfo& info,
+                                                  bool modemReducedFeatureSet1) override;
+
+  public:
+    void setResponseFunction(
+            std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse> callback);
+
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse> respond();
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h
index ba8bb0a..c617ec2 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h
@@ -22,6 +22,8 @@
 namespace android::hardware::radio::compat {
 
 class RadioData : public RadioCompatBase, public aidl::android::hardware::radio::data::BnRadioData {
+    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> respond();
+
     ::ndk::ScopedAStatus allocatePduSessionId(int32_t serial) override;
     ::ndk::ScopedAStatus cancelHandover(int32_t serial, int32_t callId) override;
     ::ndk::ScopedAStatus deactivateDataCall(
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
index 4d03063..c668af5 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
@@ -16,6 +16,7 @@
 #pragma once
 
 #include "DriverContext.h"
+#include "GuaranteedCallback.h"
 
 #include <aidl/android/hardware/radio/data/IRadioDataIndication.h>
 #include <aidl/android/hardware/radio/messaging/IRadioMessagingIndication.h>
@@ -30,13 +31,30 @@
 class RadioIndication : public V1_6::IRadioIndication {
     std::shared_ptr<DriverContext> mContext;
 
-    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> mDataCb;
-    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::data::IRadioDataIndication,
+            ::aidl::android::hardware::radio::data::IRadioDataIndicationDefault, true>
+            mDataCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::messaging::IRadioMessagingIndication,
+            ::aidl::android::hardware::radio::messaging::IRadioMessagingIndicationDefault, true>
             mMessagingCb;
-    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication> mModemCb;
-    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkIndication> mNetworkCb;
-    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> mSimCb;
-    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> mVoiceCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::modem::IRadioModemIndication,
+            ::aidl::android::hardware::radio::modem::IRadioModemIndicationDefault, true>
+            mModemCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::network::IRadioNetworkIndication,
+            ::aidl::android::hardware::radio::network::IRadioNetworkIndicationDefault, true>
+            mNetworkCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::sim::IRadioSimIndication,
+            ::aidl::android::hardware::radio::sim::IRadioSimIndicationDefault, true>
+            mSimCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::voice::IRadioVoiceIndication,
+            ::aidl::android::hardware::radio::voice::IRadioVoiceIndicationDefault, true>
+            mVoiceCb;
 
     // IRadioIndication @ 1.0
     Return<void> radioStateChanged(V1_0::RadioIndicationType type,
@@ -200,6 +218,14 @@
             std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> simCb);
     void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> voicCb);
+
+    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> dataCb();
+    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
+    messagingCb();
+    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication> modemCb();
+    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkIndication> networkCb();
+    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> simCb();
+    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> voiceCb();
 };
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h
index 0cd3381..419e9fb 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h
@@ -23,6 +23,8 @@
 
 class RadioMessaging : public RadioCompatBase,
                        public aidl::android::hardware::radio::messaging::BnRadioMessaging {
+    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse> respond();
+
     ::ndk::ScopedAStatus acknowledgeIncomingGsmSmsWithPdu(int32_t serial, bool success,
                                                           const std::string& ackPdu) override;
     ::ndk::ScopedAStatus acknowledgeLastIncomingCdmaSms(
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
index 666ff47..fdca124 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
@@ -23,6 +23,8 @@
 
 class RadioModem : public RadioCompatBase,
                    public aidl::android::hardware::radio::modem::BnRadioModem {
+    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> respond();
+
     ::ndk::ScopedAStatus enableModem(int32_t serial, bool on) override;
     ::ndk::ScopedAStatus getBasebandVersion(int32_t serial) override;
     ::ndk::ScopedAStatus getDeviceIdentity(int32_t serial) override;
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
index c776fd1..ec76300 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -23,6 +23,8 @@
 
 class RadioNetwork : public RadioCompatBase,
                      public aidl::android::hardware::radio::network::BnRadioNetwork {
+    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> respond();
+
     ::ndk::ScopedAStatus getAllowedNetworkTypesBitmap(int32_t serial) override;
     ::ndk::ScopedAStatus getAvailableBandModes(int32_t serial) override;
     ::ndk::ScopedAStatus getAvailableNetworks(int32_t serial) override;
@@ -88,6 +90,10 @@
     ::ndk::ScopedAStatus stopNetworkScan(int32_t serial) override;
     ::ndk::ScopedAStatus supplyNetworkDepersonalization(int32_t serial,
                                                         const std::string& netPin) override;
+    ::ndk::ScopedAStatus setUsageSetting(
+            int32_t serial,
+            ::aidl::android::hardware::radio::network::UsageSetting usageSetting) override;
+    ::ndk::ScopedAStatus getUsageSetting(int32_t serial) override;
 
   public:
     using RadioCompatBase::RadioCompatBase;
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
index 344864f..1f82dd1 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
@@ -16,6 +16,7 @@
 #pragma once
 
 #include "DriverContext.h"
+#include "GuaranteedCallback.h"
 
 #include <aidl/android/hardware/radio/data/IRadioDataResponse.h>
 #include <aidl/android/hardware/radio/messaging/IRadioMessagingResponse.h>
@@ -30,13 +31,24 @@
 class RadioResponse : public V1_6::IRadioResponse {
     std::shared_ptr<DriverContext> mContext;
 
-    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> mDataCb;
-    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
+    GuaranteedCallback<::aidl::android::hardware::radio::data::IRadioDataResponse,
+                       ::aidl::android::hardware::radio::data::IRadioDataResponseDefault>
+            mDataCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse,
+                       ::aidl::android::hardware::radio::messaging::IRadioMessagingResponseDefault>
             mMessagingCb;
-    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> mModemCb;
-    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> mNetworkCb;
-    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> mSimCb;
-    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> mVoiceCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::modem::IRadioModemResponse,
+                       ::aidl::android::hardware::radio::modem::IRadioModemResponseDefault>
+            mModemCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::network::IRadioNetworkResponse,
+                       ::aidl::android::hardware::radio::network::IRadioNetworkResponseDefault>
+            mNetworkCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::sim::IRadioSimResponse,
+                       ::aidl::android::hardware::radio::sim::IRadioSimResponseDefault>
+            mSimCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::voice::IRadioVoiceResponse,
+                       ::aidl::android::hardware::radio::voice::IRadioVoiceResponseDefault>
+            mVoiceCb;
 
     // IRadioResponse @ 1.0
     Return<void> getIccCardStatusResponse(const V1_0::RadioResponseInfo& info,
@@ -428,6 +440,14 @@
             std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> simCb);
     void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> voiceCb);
+
+    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> dataCb();
+    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
+    messagingCb();
+    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> modemCb();
+    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> networkCb();
+    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> simCb();
+    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> voiceCb();
 };
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
index a6b77fd..84bb68b 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
@@ -22,6 +22,8 @@
 namespace android::hardware::radio::compat {
 
 class RadioSim : public RadioCompatBase, public aidl::android::hardware::radio::sim::BnRadioSim {
+    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> respond();
+
     ::ndk::ScopedAStatus areUiccApplicationsEnabled(int32_t serial) override;
     ::ndk::ScopedAStatus changeIccPin2ForApp(int32_t serial, const std::string& oldPin2,
                                              const std::string& newPin2,
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
index 5bf93e0..5839e3a 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
@@ -23,6 +23,8 @@
 
 class RadioVoice : public RadioCompatBase,
                    public aidl::android::hardware::radio::voice::BnRadioVoice {
+    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> respond();
+
     ::ndk::ScopedAStatus acceptCall(int32_t serial) override;
     ::ndk::ScopedAStatus conference(int32_t serial) override;
     ::ndk::ScopedAStatus dial(
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp
index c7342b1..e5c33b3 100644
--- a/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp
@@ -27,67 +27,62 @@
 namespace aidl = ::aidl::android::hardware::radio::messaging;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioMessagingIndication> rmiCb) {
-    CHECK(rmiCb);
     mMessagingCb = rmiCb;
 }
 
+std::shared_ptr<aidl::IRadioMessagingIndication> RadioIndication::messagingCb() {
+    return mMessagingCb.get();
+}
+
 Return<void> RadioIndication::cdmaNewSms(V1_0::RadioIndicationType type,
                                          const V1_0::CdmaSmsMessage& msg) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->cdmaNewSms(toAidl(type), toAidl(msg));
+    messagingCb()->cdmaNewSms(toAidl(type), toAidl(msg));
     return {};
 }
 
 Return<void> RadioIndication::cdmaRuimSmsStorageFull(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->cdmaRuimSmsStorageFull(toAidl(type));
+    messagingCb()->cdmaRuimSmsStorageFull(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::newBroadcastSms(V1_0::RadioIndicationType type,
                                               const hidl_vec<uint8_t>& data) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->newBroadcastSms(toAidl(type), data);
+    messagingCb()->newBroadcastSms(toAidl(type), data);
     return {};
 }
 
 Return<void> RadioIndication::newSms(V1_0::RadioIndicationType type, const hidl_vec<uint8_t>& pdu) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->newSms(toAidl(type), pdu);
+    messagingCb()->newSms(toAidl(type), pdu);
     return {};
 }
 
 Return<void> RadioIndication::newSmsOnSim(V1_0::RadioIndicationType type, int32_t recordNumber) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->newSmsOnSim(toAidl(type), recordNumber);
+    messagingCb()->newSmsOnSim(toAidl(type), recordNumber);
     return {};
 }
 
 Return<void> RadioIndication::newSmsStatusReport(V1_0::RadioIndicationType type,
                                                  const hidl_vec<uint8_t>& pdu) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->newSmsStatusReport(toAidl(type), pdu);
+    messagingCb()->newSmsStatusReport(toAidl(type), pdu);
     return {};
 }
 
 Return<void> RadioIndication::onUssd(V1_0::RadioIndicationType type, V1_0::UssdModeType modeType,
                                      const hidl_string& msg) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->onUssd(toAidl(type), aidl::UssdModeType(modeType), msg);
+    messagingCb()->onUssd(toAidl(type), aidl::UssdModeType(modeType), msg);
     return {};
 }
 
 Return<void> RadioIndication::simSmsStorageFull(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->simSmsStorageFull(toAidl(type));
+    messagingCb()->simSmsStorageFull(toAidl(type));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp
index c1a82b5..4d94e17 100644
--- a/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp
@@ -29,6 +29,10 @@
 namespace aidl = ::aidl::android::hardware::radio::messaging;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioMessagingResponse> RadioMessaging::respond() {
+    return mCallbackManager->response().messagingCb();
+}
+
 ScopedAStatus RadioMessaging::acknowledgeIncomingGsmSmsWithPdu(  //
         int32_t serial, bool success, const std::string& ackPdu) {
     LOG_CALL << serial << ' ' << success << ' ' << ackPdu;
@@ -100,13 +104,21 @@
 
 ScopedAStatus RadioMessaging::sendCdmaSms(int32_t serial, const aidl::CdmaSmsMessage& sms) {
     LOG_CALL << serial;
-    mHal1_5->sendCdmaSms(serial, toHidl(sms));
+    if (mHal1_6) {
+        mHal1_6->sendCdmaSms_1_6(serial, toHidl(sms));
+    } else {
+        mHal1_5->sendCdmaSms(serial, toHidl(sms));
+    }
     return ok();
 }
 
 ScopedAStatus RadioMessaging::sendCdmaSmsExpectMore(int32_t serial, const aidl::CdmaSmsMessage& m) {
     LOG_CALL << serial;
-    mHal1_5->sendCdmaSmsExpectMore(serial, toHidl(m));
+    if (mHal1_6) {
+        mHal1_6->sendCdmaSmsExpectMore_1_6(serial, toHidl(m));
+    } else {
+        mHal1_5->sendCdmaSmsExpectMore(serial, toHidl(m));
+    }
     return ok();
 }
 
@@ -118,13 +130,21 @@
 
 ScopedAStatus RadioMessaging::sendSms(int32_t serial, const aidl::GsmSmsMessage& message) {
     LOG_CALL << serial;
-    mHal1_5->sendSms(serial, toHidl(message));
+    if (mHal1_6) {
+        mHal1_6->sendSms_1_6(serial, toHidl(message));
+    } else {
+        mHal1_5->sendSms(serial, toHidl(message));
+    }
     return ok();
 }
 
 ScopedAStatus RadioMessaging::sendSmsExpectMore(int32_t serial, const aidl::GsmSmsMessage& msg) {
     LOG_CALL << serial;
-    mHal1_5->sendSMSExpectMore(serial, toHidl(msg));
+    if (mHal1_6) {
+        mHal1_6->sendSmsExpectMore_1_6(serial, toHidl(msg));
+    } else {
+        mHal1_5->sendSMSExpectMore(serial, toHidl(msg));
+    }
     return ok();
 }
 
@@ -161,16 +181,10 @@
 }
 
 ScopedAStatus RadioMessaging::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioMessagingResponse>& messagingResponse,
-        const std::shared_ptr<aidl::IRadioMessagingIndication>& messagingIndication) {
-    LOG_CALL << messagingResponse << ' ' << messagingIndication;
-
-    CHECK(messagingResponse);
-    CHECK(messagingIndication);
-
-    mRadioResponse->setResponseFunction(messagingResponse);
-    mRadioIndication->setResponseFunction(messagingIndication);
-
+        const std::shared_ptr<aidl::IRadioMessagingResponse>& response,
+        const std::shared_ptr<aidl::IRadioMessagingIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp
index 379e463..24ad3d7 100644
--- a/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp
@@ -29,52 +29,49 @@
 namespace aidl = ::aidl::android::hardware::radio::messaging;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioMessagingResponse> rmrCb) {
-    CHECK(rmrCb);
     mMessagingCb = rmrCb;
 }
 
+std::shared_ptr<aidl::IRadioMessagingResponse> RadioResponse::messagingCb() {
+    return mMessagingCb.get();
+}
+
 Return<void> RadioResponse::acknowledgeIncomingGsmSmsWithPduResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->acknowledgeIncomingGsmSmsWithPduResponse(toAidl(info));
+    messagingCb()->acknowledgeIncomingGsmSmsWithPduResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::acknowledgeLastIncomingCdmaSmsResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->acknowledgeLastIncomingCdmaSmsResponse(toAidl(info));
+    messagingCb()->acknowledgeLastIncomingCdmaSmsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::acknowledgeLastIncomingGsmSmsResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->acknowledgeLastIncomingGsmSmsResponse(toAidl(info));
+    messagingCb()->acknowledgeLastIncomingGsmSmsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::cancelPendingUssdResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->cancelPendingUssdResponse(toAidl(info));
+    messagingCb()->cancelPendingUssdResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::deleteSmsOnRuimResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->deleteSmsOnRuimResponse(toAidl(info));
+    messagingCb()->deleteSmsOnRuimResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::deleteSmsOnSimResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->deleteSmsOnSimResponse(toAidl(info));
+    messagingCb()->deleteSmsOnSimResponse(toAidl(info));
     return {};
 }
 
@@ -82,162 +79,141 @@
         const V1_0::RadioResponseInfo& info,
         const hidl_vec<V1_0::CdmaBroadcastSmsConfigInfo>& configs) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->getCdmaBroadcastConfigResponse(toAidl(info), toAidl(configs));
+    messagingCb()->getCdmaBroadcastConfigResponse(toAidl(info), toAidl(configs));
     return {};
 }
 
 Return<void> RadioResponse::getGsmBroadcastConfigResponse(
         const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::GsmBroadcastSmsConfigInfo>& cfg) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->getGsmBroadcastConfigResponse(toAidl(info), toAidl(cfg));
+    messagingCb()->getGsmBroadcastConfigResponse(toAidl(info), toAidl(cfg));
     return {};
 }
 
 Return<void> RadioResponse::getSmscAddressResponse(const V1_0::RadioResponseInfo& info,
                                                    const hidl_string& smsc) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->getSmscAddressResponse(toAidl(info), smsc);
+    messagingCb()->getSmscAddressResponse(toAidl(info), smsc);
     return {};
 }
 
 Return<void> RadioResponse::reportSmsMemoryStatusResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->reportSmsMemoryStatusResponse(toAidl(info));
+    messagingCb()->reportSmsMemoryStatusResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::sendCdmaSmsExpectMoreResponse(const V1_0::RadioResponseInfo& info,
                                                           const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendCdmaSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                               const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendCdmaSmsResponse(const V1_0::RadioResponseInfo& info,
                                                 const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendCdmaSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                     const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendImsSmsResponse(const V1_0::RadioResponseInfo& info,
                                                const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendImsSmsResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendImsSmsResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendSMSExpectMoreResponse(const V1_0::RadioResponseInfo& info,
                                                       const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                           const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendSmsResponse(const V1_0::RadioResponseInfo& info,
                                             const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendSmsResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendSmsResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                 const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendSmsResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendSmsResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendUssdResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendUssdResponse(toAidl(info));
+    messagingCb()->sendUssdResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCdmaBroadcastActivationResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->setCdmaBroadcastActivationResponse(toAidl(info));
+    messagingCb()->setCdmaBroadcastActivationResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCdmaBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->setCdmaBroadcastConfigResponse(toAidl(info));
+    messagingCb()->setCdmaBroadcastConfigResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setGsmBroadcastActivationResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->setGsmBroadcastActivationResponse(toAidl(info));
+    messagingCb()->setGsmBroadcastActivationResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setGsmBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->setGsmBroadcastConfigResponse(toAidl(info));
+    messagingCb()->setGsmBroadcastConfigResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSmscAddressResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->setSmscAddressResponse(toAidl(info));
+    messagingCb()->setSmscAddressResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::writeSmsToRuimResponse(const V1_0::RadioResponseInfo& info,
                                                    uint32_t index) {
     LOG_CALL << info.serial << ' ' << index;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->writeSmsToRuimResponse(toAidl(info), index);
+    messagingCb()->writeSmsToRuimResponse(toAidl(info), index);
     return {};
 }
 
 Return<void> RadioResponse::writeSmsToSimResponse(const V1_0::RadioResponseInfo& info,
                                                   int32_t index) {
     LOG_CALL << info.serial << ' ' << index;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->writeSmsToSimResponse(toAidl(info), index);
+    messagingCb()->writeSmsToSimResponse(toAidl(info), index);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
index 8fc4da6..851c93b 100644
--- a/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
+++ b/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
@@ -29,44 +29,42 @@
 namespace aidl = ::aidl::android::hardware::radio::modem;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioModemIndication> modemCb) {
-    CHECK(modemCb);
     mModemCb = modemCb;
 }
 
+std::shared_ptr<aidl::IRadioModemIndication> RadioIndication::modemCb() {
+    return mModemCb.get();
+}
+
 Return<void> RadioIndication::hardwareConfigChanged(V1_0::RadioIndicationType type,
                                                     const hidl_vec<V1_0::HardwareConfig>& configs) {
     LOG_CALL << type;
-    CHECK_CB(mModemCb);
-    mModemCb->hardwareConfigChanged(toAidl(type), toAidl(configs));
+    modemCb()->hardwareConfigChanged(toAidl(type), toAidl(configs));
     return {};
 }
 
 Return<void> RadioIndication::modemReset(V1_0::RadioIndicationType type, const hidl_string& reasn) {
     LOG_CALL << type;
-    CHECK_CB(mModemCb);
-    mModemCb->modemReset(toAidl(type), reasn);
+    modemCb()->modemReset(toAidl(type), reasn);
     return {};
 }
 
 Return<void> RadioIndication::radioCapabilityIndication(V1_0::RadioIndicationType type,
                                                         const V1_0::RadioCapability& rc) {
     LOG_CALL << type;
-    CHECK_CB(mModemCb);
-    mModemCb->radioCapabilityIndication(toAidl(type), toAidl(rc));
+    modemCb()->radioCapabilityIndication(toAidl(type), toAidl(rc));
     return {};
 }
 
 Return<void> RadioIndication::radioStateChanged(V1_0::RadioIndicationType t, V1_0::RadioState st) {
     LOG_CALL << t;
-    CHECK_CB(mModemCb);
-    mModemCb->radioStateChanged(toAidl(t), aidl::RadioState(st));
+    modemCb()->radioStateChanged(toAidl(t), aidl::RadioState(st));
     return {};
 }
 
 Return<void> RadioIndication::rilConnected(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mModemCb);
-    mModemCb->rilConnected(toAidl(type));
+    modemCb()->rilConnected(toAidl(type));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
index 660ae9f..d28b940 100644
--- a/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
+++ b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
@@ -27,6 +27,10 @@
 namespace aidl = ::aidl::android::hardware::radio::modem;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioModemResponse> RadioModem::respond() {
+    return mCallbackManager->response().modemCb();
+}
+
 ScopedAStatus RadioModem::enableModem(int32_t serial, bool on) {
     LOG_CALL << serial;
     mHal1_5->enableModem(serial, on);
@@ -129,16 +133,10 @@
 }
 
 ScopedAStatus RadioModem::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioModemResponse>& modemResponse,
-        const std::shared_ptr<aidl::IRadioModemIndication>& modemIndication) {
-    LOG_CALL << modemResponse << ' ' << modemIndication;
-
-    CHECK(modemResponse);
-    CHECK(modemIndication);
-
-    mRadioResponse->setResponseFunction(modemResponse);
-    mRadioIndication->setResponseFunction(modemIndication);
-
+        const std::shared_ptr<aidl::IRadioModemResponse>& response,
+        const std::shared_ptr<aidl::IRadioModemIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
index 300627c..6e1a962 100644
--- a/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
+++ b/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
@@ -29,22 +29,23 @@
 namespace aidl = ::aidl::android::hardware::radio::modem;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioModemResponse> modemCb) {
-    CHECK(modemCb);
     mModemCb = modemCb;
 }
 
+std::shared_ptr<aidl::IRadioModemResponse> RadioResponse::modemCb() {
+    return mModemCb.get();
+}
+
 Return<void> RadioResponse::enableModemResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->enableModemResponse(toAidl(info));
+    modemCb()->enableModemResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::getBasebandVersionResponse(const V1_0::RadioResponseInfo& info,
                                                        const hidl_string& version) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getBasebandVersionResponse(toAidl(info), version);
+    modemCb()->getBasebandVersionResponse(toAidl(info), version);
     return {};
 }
 
@@ -52,112 +53,97 @@
         const V1_0::RadioResponseInfo& info, const hidl_string& imei, const hidl_string& imeisv,
         const hidl_string& esn, const hidl_string& meid) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getDeviceIdentityResponse(toAidl(info), imei, imeisv, esn, meid);
+    modemCb()->getDeviceIdentityResponse(toAidl(info), imei, imeisv, esn, meid);
     return {};
 }
 
 Return<void> RadioResponse::getHardwareConfigResponse(
         const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::HardwareConfig>& config) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getHardwareConfigResponse(toAidl(info), toAidl(config));
+    modemCb()->getHardwareConfigResponse(toAidl(info), toAidl(config));
     return {};
 }
 
 Return<void> RadioResponse::getModemActivityInfoResponse(
         const V1_0::RadioResponseInfo& info, const V1_0::ActivityStatsInfo& activityInfo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getModemActivityInfoResponse(toAidl(info), toAidl(activityInfo));
+    modemCb()->getModemActivityInfoResponse(toAidl(info), toAidl(activityInfo));
     return {};
 }
 
 Return<void> RadioResponse::getModemStackStatusResponse(const V1_0::RadioResponseInfo& info,
                                                         bool isEnabled) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getModemStackStatusResponse(toAidl(info), isEnabled);
+    modemCb()->getModemStackStatusResponse(toAidl(info), isEnabled);
     return {};
 }
 
 Return<void> RadioResponse::getRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
                                                        const V1_0::RadioCapability& rc) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getRadioCapabilityResponse(toAidl(info), toAidl(rc));
+    modemCb()->getRadioCapabilityResponse(toAidl(info), toAidl(rc));
     return {};
 }
 
 Return<void> RadioResponse::nvReadItemResponse(const V1_0::RadioResponseInfo& info,
                                                const hidl_string& result) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->nvReadItemResponse(toAidl(info), result);
+    modemCb()->nvReadItemResponse(toAidl(info), result);
     return {};
 }
 
 Return<void> RadioResponse::nvResetConfigResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->nvResetConfigResponse(toAidl(info));
+    modemCb()->nvResetConfigResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::nvWriteCdmaPrlResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->nvWriteCdmaPrlResponse(toAidl(info));
+    modemCb()->nvWriteCdmaPrlResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::nvWriteItemResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->nvWriteItemResponse(toAidl(info));
+    modemCb()->nvWriteItemResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::requestShutdownResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->requestShutdownResponse(toAidl(info));
+    modemCb()->requestShutdownResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::sendDeviceStateResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->sendDeviceStateResponse(toAidl(info));
+    modemCb()->sendDeviceStateResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
                                                        const V1_0::RadioCapability& rc) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->setRadioCapabilityResponse(toAidl(info), toAidl(rc));
+    modemCb()->setRadioCapabilityResponse(toAidl(info), toAidl(rc));
     return {};
 }
 
 Return<void> RadioResponse::setRadioPowerResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->setRadioPowerResponse(toAidl(info));
+    modemCb()->setRadioPowerResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setRadioPowerResponse_1_5(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->setRadioPowerResponse(toAidl(info));
+    modemCb()->setRadioPowerResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setRadioPowerResponse_1_6(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->setRadioPowerResponse(toAidl(info));
+    modemCb()->setRadioPowerResponse(toAidl(info));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp b/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
index 899b133..d4cbdbc 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
@@ -30,23 +30,24 @@
 namespace aidl = ::aidl::android::hardware::radio::network;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioNetworkIndication> netCb) {
-    CHECK(netCb);
     mNetworkCb = netCb;
 }
 
+std::shared_ptr<aidl::IRadioNetworkIndication> RadioIndication::networkCb() {
+    return mNetworkCb.get();
+}
+
 Return<void> RadioIndication::barringInfoChanged(V1_0::RadioIndicationType type,
                                                  const V1_5::CellIdentity& cellIdentity,
                                                  const hidl_vec<V1_5::BarringInfo>& barringInfos) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->barringInfoChanged(toAidl(type), toAidl(cellIdentity), toAidl(barringInfos));
+    networkCb()->barringInfoChanged(toAidl(type), toAidl(cellIdentity), toAidl(barringInfos));
     return {};
 }
 
 Return<void> RadioIndication::cdmaPrlChanged(V1_0::RadioIndicationType type, int32_t version) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->cdmaPrlChanged(toAidl(type), version);
+    networkCb()->cdmaPrlChanged(toAidl(type), version);
     return {};
 }
 
@@ -74,32 +75,28 @@
 Return<void> RadioIndication::cellInfoList_1_5(V1_0::RadioIndicationType type,
                                                const hidl_vec<V1_5::CellInfo>& records) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->cellInfoList(toAidl(type), toAidl(records));
+    networkCb()->cellInfoList(toAidl(type), toAidl(records));
     return {};
 }
 
 Return<void> RadioIndication::cellInfoList_1_6(V1_0::RadioIndicationType type,
                                                const hidl_vec<V1_6::CellInfo>& records) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->cellInfoList(toAidl(type), toAidl(records));
+    networkCb()->cellInfoList(toAidl(type), toAidl(records));
     return {};
 }
 
 Return<void> RadioIndication::currentLinkCapacityEstimate(V1_0::RadioIndicationType type,
                                                           const V1_2::LinkCapacityEstimate& lce) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
+    networkCb()->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
     return {};
 }
 
 Return<void> RadioIndication::currentLinkCapacityEstimate_1_6(
         V1_0::RadioIndicationType type, const V1_6::LinkCapacityEstimate& lce) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
+    networkCb()->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
     return {};
 }
 
@@ -113,16 +110,14 @@
 Return<void> RadioIndication::currentPhysicalChannelConfigs_1_4(
         V1_0::RadioIndicationType type, const hidl_vec<V1_4::PhysicalChannelConfig>& configs) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
+    networkCb()->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
     return {};
 }
 
 Return<void> RadioIndication::currentPhysicalChannelConfigs_1_6(
         V1_0::RadioIndicationType type, const hidl_vec<V1_6::PhysicalChannelConfig>& configs) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
+    networkCb()->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
     return {};
 }
 
@@ -143,23 +138,20 @@
 Return<void> RadioIndication::currentSignalStrength_1_4(
         V1_0::RadioIndicationType type, const V1_4::SignalStrength& signalStrength) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentSignalStrength(toAidl(type), toAidl(signalStrength));
+    networkCb()->currentSignalStrength(toAidl(type), toAidl(signalStrength));
     return {};
 }
 
 Return<void> RadioIndication::currentSignalStrength_1_6(
         V1_0::RadioIndicationType type, const V1_6::SignalStrength& signalStrength) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentSignalStrength(toAidl(type), toAidl(signalStrength));
+    networkCb()->currentSignalStrength(toAidl(type), toAidl(signalStrength));
     return {};
 }
 
 Return<void> RadioIndication::imsNetworkStateChanged(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->imsNetworkStateChanged(toAidl(type));
+    networkCb()->imsNetworkStateChanged(toAidl(type));
     return {};
 }
 
@@ -187,31 +179,27 @@
 Return<void> RadioIndication::networkScanResult_1_5(V1_0::RadioIndicationType type,
                                                     const V1_5::NetworkScanResult& result) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->networkScanResult(toAidl(type), toAidl(result));
+    networkCb()->networkScanResult(toAidl(type), toAidl(result));
     return {};
 }
 
 Return<void> RadioIndication::networkScanResult_1_6(V1_0::RadioIndicationType type,
                                                     const V1_6::NetworkScanResult& result) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->networkScanResult(toAidl(type), toAidl(result));
+    networkCb()->networkScanResult(toAidl(type), toAidl(result));
     return {};
 }
 
 Return<void> RadioIndication::networkStateChanged(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->networkStateChanged(toAidl(type));
+    networkCb()->networkStateChanged(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::nitzTimeReceived(V1_0::RadioIndicationType type,
                                                const hidl_string& nitzTime, uint64_t receivedTime) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->nitzTimeReceived(toAidl(type), nitzTime, receivedTime, 0);
+    networkCb()->nitzTimeReceived(toAidl(type), nitzTime, receivedTime, 0);
     return {};
 }
 
@@ -220,33 +208,29 @@
         const hidl_string& chosenPlmn, hidl_bitfield<V1_5::Domain> domain, int32_t causeCode,
         int32_t additionalCauseCode) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->registrationFailed(toAidl(type), toAidl(cellIdentity), chosenPlmn,
-                                   aidl::Domain(domain), causeCode, additionalCauseCode);
+    networkCb()->registrationFailed(toAidl(type), toAidl(cellIdentity), chosenPlmn,
+                                    aidl::Domain(domain), causeCode, additionalCauseCode);
     return {};
 }
 
 Return<void> RadioIndication::restrictedStateChanged(V1_0::RadioIndicationType type,
                                                      V1_0::PhoneRestrictedState state) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->restrictedStateChanged(toAidl(type), aidl::PhoneRestrictedState(state));
+    networkCb()->restrictedStateChanged(toAidl(type), aidl::PhoneRestrictedState(state));
     return {};
 }
 
 Return<void> RadioIndication::suppSvcNotify(V1_0::RadioIndicationType type,
                                             const V1_0::SuppSvcNotification& suppSvc) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->suppSvcNotify(toAidl(type), toAidl(suppSvc));
+    networkCb()->suppSvcNotify(toAidl(type), toAidl(suppSvc));
     return {};
 }
 
 Return<void> RadioIndication::voiceRadioTechChanged(V1_0::RadioIndicationType type,
                                                     V1_0::RadioTechnology rat) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->voiceRadioTechChanged(toAidl(type), RadioTechnology(rat));
+    networkCb()->voiceRadioTechChanged(toAidl(type), RadioTechnology(rat));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
index af0bc46..8bfa0bb 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -33,6 +33,10 @@
 namespace aidl = ::aidl::android::hardware::radio::network;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioNetworkResponse> RadioNetwork::respond() {
+    return mCallbackManager->response().networkCb();
+}
+
 ScopedAStatus RadioNetwork::getAllowedNetworkTypesBitmap(int32_t serial) {
     LOG_CALL << serial;
     if (mHal1_6) {
@@ -69,13 +73,21 @@
 
 ScopedAStatus RadioNetwork::getCellInfoList(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getCellInfoList(serial);
+    if (mHal1_6) {
+        mHal1_6->getCellInfoList_1_6(serial);
+    } else {
+        mHal1_5->getCellInfoList(serial);
+    }
     return ok();
 }
 
 ScopedAStatus RadioNetwork::getDataRegistrationState(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getDataRegistrationState(serial);
+    if (mHal1_6) {
+        mHal1_6->getDataRegistrationState_1_6(serial);
+    } else {
+        mHal1_5->getDataRegistrationState_1_5(serial);
+    }
     return ok();
 }
 
@@ -99,7 +111,11 @@
 
 ScopedAStatus RadioNetwork::getSignalStrength(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getSignalStrength(serial);
+    if (mHal1_6) {
+        mHal1_6->getSignalStrength_1_6(serial);
+    } else {
+        mHal1_5->getSignalStrength_1_4(serial);
+    }
     return ok();
 }
 
@@ -108,7 +124,7 @@
     if (mHal1_6) {
         mHal1_6->getSystemSelectionChannels(serial);
     } else {
-        respond().getSystemSelectionChannelsResponse(notSupported(serial), {});
+        respond()->getSystemSelectionChannelsResponse(notSupported(serial), {});
     }
     return ok();
 }
@@ -121,7 +137,11 @@
 
 ScopedAStatus RadioNetwork::getVoiceRegistrationState(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getVoiceRegistrationState(serial);
+    if (mHal1_6) {
+        mHal1_6->getVoiceRegistrationState_1_6(serial);
+    } else {
+        mHal1_5->getVoiceRegistrationState_1_5(serial);
+    }
     return ok();
 }
 
@@ -130,7 +150,7 @@
     if (mHal1_6) {
         mHal1_6->isNrDualConnectivityEnabled(serial);
     } else {
-        respond().isNrDualConnectivityEnabledResponse(notSupported(serial), false);
+        respond()->isNrDualConnectivityEnabledResponse(notSupported(serial), false);
     }
     return ok();
 }
@@ -179,7 +199,7 @@
 
 ScopedAStatus RadioNetwork::setIndicationFilter(int32_t serial, aidl::IndicationFilter indFilter) {
     LOG_CALL << serial;
-    mHal1_5->setIndicationFilter(serial, toHidlBitfield<V1_0::IndicationFilter>(indFilter));
+    mHal1_5->setIndicationFilter_1_5(serial, toHidlBitfield<V1_5::IndicationFilter>(indFilter));
     return ok();
 }
 
@@ -188,9 +208,9 @@
         const std::vector<int32_t>& thrDownlinkKbps, const std::vector<int32_t>& thrUplinkKbps,
         AccessNetwork accessNetwork) {
     LOG_CALL << serial;
-    mHal1_5->setLinkCapacityReportingCriteria(  //
+    mHal1_5->setLinkCapacityReportingCriteria_1_5(  //
             serial, hysteresisMs, hysteresisDlKbps, hysteresisUlKbps, thrDownlinkKbps,
-            thrUplinkKbps, V1_2::AccessNetwork(accessNetwork));
+            thrUplinkKbps, V1_5::AccessNetwork(accessNetwork));
     return ok();
 }
 
@@ -219,22 +239,16 @@
     if (mHal1_6) {
         mHal1_6->setNrDualConnectivityState(serial, V1_6::NrDualConnectivityState(st));
     } else {
-        respond().setNrDualConnectivityStateResponse(notSupported(serial));
+        respond()->setNrDualConnectivityStateResponse(notSupported(serial));
     }
     return ok();
 }
 
 ScopedAStatus RadioNetwork::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioNetworkResponse>& networkResponse,
-        const std::shared_ptr<aidl::IRadioNetworkIndication>& networkIndication) {
-    LOG_CALL << networkResponse << ' ' << networkIndication;
-
-    CHECK(networkResponse);
-    CHECK(networkIndication);
-
-    mRadioResponse->setResponseFunction(networkResponse);
-    mRadioIndication->setResponseFunction(networkIndication);
-
+        const std::shared_ptr<aidl::IRadioNetworkResponse>& response,
+        const std::shared_ptr<aidl::IRadioNetworkIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
@@ -278,4 +292,19 @@
     return ok();
 }
 
+// TODO(b/210498497): is there a cleaner way to send a response back to Android, even though these
+// methods must never be called?
+ScopedAStatus RadioNetwork::setUsageSetting(
+        int32_t ser, ::aidl::android::hardware::radio::network::UsageSetting) {
+    LOG_CALL << ser;
+    LOG(ERROR) << "setUsageSetting is unsupported by HIDL HALs";
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getUsageSetting(int32_t ser) {
+    LOG_CALL << ser;
+    LOG(ERROR) << "getUsageSetting is unsupported by HIDL HALs";
+    return ok();
+}
+
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp b/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
index 81f7775..bab1d4a 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
@@ -33,25 +33,26 @@
 namespace aidl = ::aidl::android::hardware::radio::network;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioNetworkResponse> netCb) {
-    CHECK(netCb);
     mNetworkCb = netCb;
 }
 
+std::shared_ptr<aidl::IRadioNetworkResponse> RadioResponse::networkCb() {
+    return mNetworkCb.get();
+}
+
 Return<void> RadioResponse::getAllowedNetworkTypesBitmapResponse(
         const V1_6::RadioResponseInfo& info,
         hidl_bitfield<V1_4::RadioAccessFamily> networkTypeBitmap) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getAllowedNetworkTypesBitmapResponse(toAidl(info),
-                                                     RadioAccessFamily(networkTypeBitmap));
+    networkCb()->getAllowedNetworkTypesBitmapResponse(toAidl(info),
+                                                      RadioAccessFamily(networkTypeBitmap));
     return {};
 }
 
 Return<void> RadioResponse::getPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info,
                                                             V1_0::PreferredNetworkType nwType) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getAllowedNetworkTypesBitmapResponse(  //
+    networkCb()->getAllowedNetworkTypesBitmapResponse(  //
             toAidl(info), RadioAccessFamily(getRafFromNetworkType(nwType)));
     return {};
 }
@@ -66,16 +67,14 @@
 Return<void> RadioResponse::getAvailableBandModesResponse(
         const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::RadioBandMode>& bandModes) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getAvailableBandModesResponse(toAidl(info), toAidl(bandModes));
+    networkCb()->getAvailableBandModesResponse(toAidl(info), toAidl(bandModes));
     return {};
 }
 
 Return<void> RadioResponse::getAvailableNetworksResponse(
         const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::OperatorInfo>& networkInfos) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getAvailableNetworksResponse(toAidl(info), toAidl(networkInfos));
+    networkCb()->getAvailableNetworksResponse(toAidl(info), toAidl(networkInfos));
     return {};
 }
 
@@ -83,16 +82,14 @@
         const V1_0::RadioResponseInfo& info, const V1_5::CellIdentity& cellIdentity,
         const hidl_vec<V1_5::BarringInfo>& barringInfos) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getBarringInfoResponse(toAidl(info), toAidl(cellIdentity), toAidl(barringInfos));
+    networkCb()->getBarringInfoResponse(toAidl(info), toAidl(cellIdentity), toAidl(barringInfos));
     return {};
 }
 
 Return<void> RadioResponse::getCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info,
                                                              V1_0::CdmaRoamingType type) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getCdmaRoamingPreferenceResponse(toAidl(info), aidl::CdmaRoamingType(type));
+    networkCb()->getCdmaRoamingPreferenceResponse(toAidl(info), aidl::CdmaRoamingType(type));
     return {};
 }
 
@@ -120,16 +117,14 @@
 Return<void> RadioResponse::getCellInfoListResponse_1_5(const V1_0::RadioResponseInfo& info,
                                                         const hidl_vec<V1_5::CellInfo>& cellInfo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
+    networkCb()->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
     return {};
 }
 
 Return<void> RadioResponse::getCellInfoListResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                         const hidl_vec<V1_6::CellInfo>& cellInfo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
+    networkCb()->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
     return {};
 }
 
@@ -157,25 +152,22 @@
 Return<void> RadioResponse::getDataRegistrationStateResponse_1_5(
         const V1_0::RadioResponseInfo& info, const V1_5::RegStateResult& dataRegResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
+    networkCb()->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
     return {};
 }
 
 Return<void> RadioResponse::getDataRegistrationStateResponse_1_6(
         const V1_6::RadioResponseInfo& info, const V1_6::RegStateResult& dataRegResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
+    networkCb()->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
     return {};
 }
 
 Return<void> RadioResponse::getImsRegistrationStateResponse(  //
         const V1_0::RadioResponseInfo& info, bool isRegd, V1_0::RadioTechnologyFamily ratFamily) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getImsRegistrationStateResponse(toAidl(info), isRegd,
-                                                RadioTechnologyFamily(ratFamily));
+    networkCb()->getImsRegistrationStateResponse(toAidl(info), isRegd,
+                                                 RadioTechnologyFamily(ratFamily));
     return {};
 }
 
@@ -189,8 +181,7 @@
 Return<void> RadioResponse::getNetworkSelectionModeResponse(const V1_0::RadioResponseInfo& info,
                                                             bool manual) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getNetworkSelectionModeResponse(toAidl(info), manual);
+    networkCb()->getNetworkSelectionModeResponse(toAidl(info), manual);
     return {};
 }
 
@@ -198,8 +189,7 @@
         const V1_0::RadioResponseInfo& info, const hidl_string& longName,
         const hidl_string& shortName, const hidl_string& numeric) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getOperatorResponse(toAidl(info), longName, shortName, numeric);
+    networkCb()->getOperatorResponse(toAidl(info), longName, shortName, numeric);
     return {};
 }
 
@@ -220,16 +210,14 @@
 Return<void> RadioResponse::getSignalStrengthResponse_1_4(
         const V1_0::RadioResponseInfo& info, const V1_4::SignalStrength& signalStrength) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
+    networkCb()->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
     return {};
 }
 
 Return<void> RadioResponse::getSignalStrengthResponse_1_6(
         const V1_6::RadioResponseInfo& info, const V1_6::SignalStrength& signalStrength) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
+    networkCb()->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
     return {};
 }
 
@@ -237,16 +225,14 @@
         const V1_6::RadioResponseInfo& info,
         const hidl_vec<V1_5::RadioAccessSpecifier>& specifiers) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getSystemSelectionChannelsResponse(toAidl(info), toAidl(specifiers));
+    networkCb()->getSystemSelectionChannelsResponse(toAidl(info), toAidl(specifiers));
     return {};
 }
 
 Return<void> RadioResponse::getVoiceRadioTechnologyResponse(const V1_0::RadioResponseInfo& info,
                                                             V1_0::RadioTechnology rat) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getVoiceRadioTechnologyResponse(toAidl(info), RadioTechnology(rat));
+    networkCb()->getVoiceRadioTechnologyResponse(toAidl(info), RadioTechnology(rat));
     return {};
 }
 
@@ -267,24 +253,21 @@
 Return<void> RadioResponse::getVoiceRegistrationStateResponse_1_5(
         const V1_0::RadioResponseInfo& info, const V1_5::RegStateResult& voiceRegResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
+    networkCb()->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
     return {};
 }
 
 Return<void> RadioResponse::getVoiceRegistrationStateResponse_1_6(
         const V1_6::RadioResponseInfo& info, const V1_6::RegStateResult& voiceRegResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
+    networkCb()->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
     return {};
 }
 
 Return<void> RadioResponse::isNrDualConnectivityEnabledResponse(const V1_6::RadioResponseInfo& info,
                                                                 bool isEnabled) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->isNrDualConnectivityEnabledResponse(toAidl(info), isEnabled);
+    networkCb()->isNrDualConnectivityEnabledResponse(toAidl(info), isEnabled);
     return {};
 }
 
@@ -297,15 +280,13 @@
 
 Return<void> RadioResponse::setAllowedNetworkTypesBitmapResponse(const V1_6::RadioResponseInfo& i) {
     LOG_CALL << i.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setAllowedNetworkTypesBitmapResponse(toAidl(i));
+    networkCb()->setAllowedNetworkTypesBitmapResponse(toAidl(i));
     return {};
 }
 
 Return<void> RadioResponse::setPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setAllowedNetworkTypesBitmapResponse(toAidl(info));
+    networkCb()->setAllowedNetworkTypesBitmapResponse(toAidl(info));
     return {};
 }
 
@@ -318,174 +299,151 @@
 
 Return<void> RadioResponse::setBandModeResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setBandModeResponse(toAidl(info));
+    networkCb()->setBandModeResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setBarringPasswordResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setBarringPasswordResponse(toAidl(info));
+    networkCb()->setBarringPasswordResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setCdmaRoamingPreferenceResponse(toAidl(info));
+    networkCb()->setCdmaRoamingPreferenceResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCellInfoListRateResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setCellInfoListRateResponse(toAidl(info));
+    networkCb()->setCellInfoListRateResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setIndicationFilterResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setIndicationFilterResponse(toAidl(info));
+    networkCb()->setIndicationFilterResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setIndicationFilterResponse_1_5(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setIndicationFilterResponse(toAidl(info));
+    networkCb()->setIndicationFilterResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setLinkCapacityReportingCriteriaResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setLinkCapacityReportingCriteriaResponse(toAidl(info));
+    networkCb()->setLinkCapacityReportingCriteriaResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setLinkCapacityReportingCriteriaResponse_1_5(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setLinkCapacityReportingCriteriaResponse(toAidl(info));
+    networkCb()->setLinkCapacityReportingCriteriaResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setLocationUpdatesResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setLocationUpdatesResponse(toAidl(info));
+    networkCb()->setLocationUpdatesResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setNetworkSelectionModeAutomaticResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setNetworkSelectionModeAutomaticResponse(toAidl(info));
+    networkCb()->setNetworkSelectionModeAutomaticResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setNetworkSelectionModeManualResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setNetworkSelectionModeManualResponse(toAidl(info));
+    networkCb()->setNetworkSelectionModeManualResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setNetworkSelectionModeManualResponse_1_5(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setNetworkSelectionModeManualResponse(toAidl(info));
+    networkCb()->setNetworkSelectionModeManualResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setNrDualConnectivityStateResponse(
         const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setNrDualConnectivityStateResponse(toAidl(info));
+    networkCb()->setNrDualConnectivityStateResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSignalStrengthReportingCriteriaResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setSignalStrengthReportingCriteriaResponse(toAidl(info));
+    networkCb()->setSignalStrengthReportingCriteriaResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSignalStrengthReportingCriteriaResponse_1_5(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setSignalStrengthReportingCriteriaResponse(toAidl(info));
+    networkCb()->setSignalStrengthReportingCriteriaResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSuppServiceNotificationsResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setSuppServiceNotificationsResponse(toAidl(info));
+    networkCb()->setSuppServiceNotificationsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSystemSelectionChannelsResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setSystemSelectionChannelsResponse(toAidl(info));
+    networkCb()->setSystemSelectionChannelsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSystemSelectionChannelsResponse_1_5(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setSystemSelectionChannelsResponse(toAidl(info));
+    networkCb()->setSystemSelectionChannelsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::startNetworkScanResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->startNetworkScanResponse(toAidl(info));
+    networkCb()->startNetworkScanResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::startNetworkScanResponse_1_4(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->startNetworkScanResponse(toAidl(info));
+    networkCb()->startNetworkScanResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::startNetworkScanResponse_1_5(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->startNetworkScanResponse(toAidl(info));
+    networkCb()->startNetworkScanResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::stopNetworkScanResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->stopNetworkScanResponse(toAidl(info));
+    networkCb()->stopNetworkScanResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::supplyNetworkDepersonalizationResponse(
         const V1_0::RadioResponseInfo& info, int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->supplyNetworkDepersonalizationResponse(toAidl(info), remainingRetries);
+    networkCb()->supplyNetworkDepersonalizationResponse(toAidl(info), remainingRetries);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp
index 6b906c6..3938e00 100644
--- a/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp
+++ b/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp
@@ -29,29 +29,29 @@
 namespace aidl = ::aidl::android::hardware::radio::sim;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioSimIndication> simCb) {
-    CHECK(simCb);
     mSimCb = simCb;
 }
 
+std::shared_ptr<aidl::IRadioSimIndication> RadioIndication::simCb() {
+    return mSimCb.get();
+}
+
 Return<void> RadioIndication::carrierInfoForImsiEncryption(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->carrierInfoForImsiEncryption(toAidl(type));
+    simCb()->carrierInfoForImsiEncryption(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::cdmaSubscriptionSourceChanged(
         V1_0::RadioIndicationType type, V1_0::CdmaSubscriptionSource cdmaSource) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->cdmaSubscriptionSourceChanged(toAidl(type), aidl::CdmaSubscriptionSource(cdmaSource));
+    simCb()->cdmaSubscriptionSourceChanged(toAidl(type), aidl::CdmaSubscriptionSource(cdmaSource));
     return {};
 }
 
 Return<void> RadioIndication::simPhonebookChanged(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->simPhonebookChanged(toAidl(type));
+    simCb()->simPhonebookChanged(toAidl(type));
     return {};
 }
 
@@ -59,62 +59,54 @@
         V1_0::RadioIndicationType type, V1_6::PbReceivedStatus status,
         const hidl_vec<V1_6::PhonebookRecordInfo>& rec) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->simPhonebookRecordsReceived(toAidl(type), aidl::PbReceivedStatus(status), toAidl(rec));
+    simCb()->simPhonebookRecordsReceived(toAidl(type), aidl::PbReceivedStatus(status), toAidl(rec));
     return {};
 }
 
 Return<void> RadioIndication::simRefresh(V1_0::RadioIndicationType type,
                                          const V1_0::SimRefreshResult& refreshResult) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->simRefresh(toAidl(type), toAidl(refreshResult));
+    simCb()->simRefresh(toAidl(type), toAidl(refreshResult));
     return {};
 }
 
 Return<void> RadioIndication::simStatusChanged(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->simStatusChanged(toAidl(type));
+    simCb()->simStatusChanged(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::stkEventNotify(V1_0::RadioIndicationType type,
                                              const hidl_string& cmd) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->stkEventNotify(toAidl(type), cmd);
+    simCb()->stkEventNotify(toAidl(type), cmd);
     return {};
 }
 
 Return<void> RadioIndication::stkProactiveCommand(V1_0::RadioIndicationType type,
                                                   const hidl_string& cmd) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->stkProactiveCommand(toAidl(type), cmd);
+    simCb()->stkProactiveCommand(toAidl(type), cmd);
     return {};
 }
 
 Return<void> RadioIndication::stkSessionEnd(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->stkSessionEnd(toAidl(type));
+    simCb()->stkSessionEnd(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::subscriptionStatusChanged(V1_0::RadioIndicationType type,
                                                         bool activate) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->subscriptionStatusChanged(toAidl(type), activate);
+    simCb()->subscriptionStatusChanged(toAidl(type), activate);
     return {};
 }
 
 Return<void> RadioIndication::uiccApplicationsEnablementChanged(V1_0::RadioIndicationType type,
                                                                 bool enabled) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->uiccApplicationsEnablementChanged(toAidl(type), enabled);
+    simCb()->uiccApplicationsEnablementChanged(toAidl(type), enabled);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp
index 2dfbc50..3ad9130 100644
--- a/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp
+++ b/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp
@@ -29,48 +29,46 @@
 namespace aidl = ::aidl::android::hardware::radio::sim;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioSimResponse> simCb) {
-    CHECK(simCb);
     mSimCb = simCb;
 }
 
+std::shared_ptr<aidl::IRadioSimResponse> RadioResponse::simCb() {
+    return mSimCb.get();
+}
+
 Return<void> RadioResponse::areUiccApplicationsEnabledResponse(const V1_0::RadioResponseInfo& info,
                                                                bool enabled) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->areUiccApplicationsEnabledResponse(toAidl(info), enabled);
+    simCb()->areUiccApplicationsEnabledResponse(toAidl(info), enabled);
     return {};
 }
 
 Return<void> RadioResponse::changeIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
                                                         int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->changeIccPin2ForAppResponse(toAidl(info), remainingRetries);
+    simCb()->changeIccPin2ForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
 Return<void> RadioResponse::changeIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
                                                        int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->changeIccPinForAppResponse(toAidl(info), remainingRetries);
+    simCb()->changeIccPinForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
 Return<void> RadioResponse::enableUiccApplicationsResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->enableUiccApplicationsResponse(toAidl(info));
+    simCb()->enableUiccApplicationsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::getAllowedCarriersResponse(  //
         const V1_0::RadioResponseInfo& info, bool allAllowed, const V1_0::CarrierRestrictions& cr) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
     aidl::CarrierRestrictions aidlCr = toAidl(cr);
     if (allAllowed) aidlCr = {};
-    mSimCb->getAllowedCarriersResponse(toAidl(info), aidlCr, {});
+    simCb()->getAllowedCarriersResponse(toAidl(info), aidlCr, {});
     return {};
 }
 
@@ -78,9 +76,8 @@
         const V1_0::RadioResponseInfo& info, const V1_4::CarrierRestrictionsWithPriority& carriers,
         V1_4::SimLockMultiSimPolicy multiSimPolicy) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getAllowedCarriersResponse(toAidl(info), toAidl(carriers),
-                                       aidl::SimLockMultiSimPolicy(multiSimPolicy));
+    simCb()->getAllowedCarriersResponse(toAidl(info), toAidl(carriers),
+                                        aidl::SimLockMultiSimPolicy(multiSimPolicy));
     return {};
 }
 
@@ -88,133 +85,116 @@
         const V1_0::RadioResponseInfo& info, const hidl_string& mdn, const hidl_string& hSid,
         const hidl_string& hNid, const hidl_string& min, const hidl_string& prl) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getCdmaSubscriptionResponse(toAidl(info), mdn, hSid, hNid, min, prl);
+    simCb()->getCdmaSubscriptionResponse(toAidl(info), mdn, hSid, hNid, min, prl);
     return {};
 }
 
 Return<void> RadioResponse::getCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info,
                                                               V1_0::CdmaSubscriptionSource s) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getCdmaSubscriptionSourceResponse(toAidl(info), aidl::CdmaSubscriptionSource(s));
+    simCb()->getCdmaSubscriptionSourceResponse(toAidl(info), aidl::CdmaSubscriptionSource(s));
     return {};
 }
 
 Return<void> RadioResponse::getFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
                                                           int32_t response) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getFacilityLockForAppResponse(toAidl(info), response);
+    simCb()->getFacilityLockForAppResponse(toAidl(info), response);
     return {};
 }
 
 Return<void> RadioResponse::getIccCardStatusResponse(const V1_0::RadioResponseInfo& info,
                                                      const V1_0::CardStatus& cardStatus) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
     return {};
 }
 
 Return<void> RadioResponse::getIccCardStatusResponse_1_2(const V1_0::RadioResponseInfo& info,
                                                          const V1_2::CardStatus& cardStatus) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
     return {};
 }
 
 Return<void> RadioResponse::getIccCardStatusResponse_1_4(const V1_0::RadioResponseInfo& info,
                                                          const V1_4::CardStatus& cardStatus) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
     return {};
 }
 
 Return<void> RadioResponse::getIccCardStatusResponse_1_5(const V1_0::RadioResponseInfo& info,
                                                          const V1_5::CardStatus& cardStatus) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
     return {};
 }
 
 Return<void> RadioResponse::getIMSIForAppResponse(const V1_0::RadioResponseInfo& info,
                                                   const hidl_string& imsi) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getImsiForAppResponse(toAidl(info), imsi);
+    simCb()->getImsiForAppResponse(toAidl(info), imsi);
     return {};
 }
 
 Return<void> RadioResponse::getSimPhonebookCapacityResponse(
         const V1_6::RadioResponseInfo& info, const V1_6::PhonebookCapacity& capacity) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getSimPhonebookCapacityResponse(toAidl(info), toAidl(capacity));
+    simCb()->getSimPhonebookCapacityResponse(toAidl(info), toAidl(capacity));
     return {};
 }
 
 Return<void> RadioResponse::getSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getSimPhonebookRecordsResponse(toAidl(info));
+    simCb()->getSimPhonebookRecordsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::iccCloseLogicalChannelResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->iccCloseLogicalChannelResponse(toAidl(info));
+    simCb()->iccCloseLogicalChannelResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::iccIOForAppResponse(const V1_0::RadioResponseInfo& info,
                                                 const V1_0::IccIoResult& iccIo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->iccIoForAppResponse(toAidl(info), toAidl(iccIo));
+    simCb()->iccIoForAppResponse(toAidl(info), toAidl(iccIo));
     return {};
 }
 
 Return<void> RadioResponse::iccOpenLogicalChannelResponse(  //
         const V1_0::RadioResponseInfo& info, int32_t chanId, const hidl_vec<int8_t>& selectResp) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->iccOpenLogicalChannelResponse(toAidl(info), chanId, toAidl(selectResp));
+    simCb()->iccOpenLogicalChannelResponse(toAidl(info), chanId, toAidl(selectResp));
     return {};
 }
 
 Return<void> RadioResponse::iccTransmitApduBasicChannelResponse(const V1_0::RadioResponseInfo& info,
                                                                 const V1_0::IccIoResult& result) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->iccTransmitApduBasicChannelResponse(toAidl(info), toAidl(result));
+    simCb()->iccTransmitApduBasicChannelResponse(toAidl(info), toAidl(result));
     return {};
 }
 
 Return<void> RadioResponse::iccTransmitApduLogicalChannelResponse(
         const V1_0::RadioResponseInfo& info, const V1_0::IccIoResult& result) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->iccTransmitApduLogicalChannelResponse(toAidl(info), toAidl(result));
+    simCb()->iccTransmitApduLogicalChannelResponse(toAidl(info), toAidl(result));
     return {};
 }
 
 Return<void> RadioResponse::reportStkServiceIsRunningResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->reportStkServiceIsRunningResponse(toAidl(info));
+    simCb()->reportStkServiceIsRunningResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::requestIccSimAuthenticationResponse(const V1_0::RadioResponseInfo& info,
                                                                 const V1_0::IccIoResult& result) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->requestIccSimAuthenticationResponse(toAidl(info), toAidl(result));
+    simCb()->requestIccSimAuthenticationResponse(toAidl(info), toAidl(result));
     return {};
 }
 
@@ -228,121 +208,105 @@
 Return<void> RadioResponse::sendEnvelopeResponse(const V1_0::RadioResponseInfo& info,
                                                  const hidl_string& commandResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->sendEnvelopeResponse(toAidl(info), commandResponse);
+    simCb()->sendEnvelopeResponse(toAidl(info), commandResponse);
     return {};
 }
 
 Return<void> RadioResponse::sendEnvelopeWithStatusResponse(const V1_0::RadioResponseInfo& info,
                                                            const V1_0::IccIoResult& iccIo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->sendEnvelopeWithStatusResponse(toAidl(info), toAidl(iccIo));
+    simCb()->sendEnvelopeWithStatusResponse(toAidl(info), toAidl(iccIo));
     return {};
 }
 
 Return<void> RadioResponse::sendTerminalResponseToSimResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->sendTerminalResponseToSimResponse(toAidl(info));
+    simCb()->sendTerminalResponseToSimResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setAllowedCarriersResponse(const V1_0::RadioResponseInfo& info,
                                                        int32_t numAllowed) {
     LOG_CALL << info.serial << ' ' << numAllowed;
-    CHECK_CB(mSimCb);
-    mSimCb->setAllowedCarriersResponse(toAidl(info));
+    simCb()->setAllowedCarriersResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setAllowedCarriersResponse_1_4(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setAllowedCarriersResponse(toAidl(info));
+    simCb()->setAllowedCarriersResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCarrierInfoForImsiEncryptionResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setCarrierInfoForImsiEncryptionResponse(toAidl(info));
+    simCb()->setCarrierInfoForImsiEncryptionResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setCdmaSubscriptionSourceResponse(toAidl(info));
+    simCb()->setCdmaSubscriptionSourceResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
                                                           int32_t retry) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setFacilityLockForAppResponse(toAidl(info), retry);
+    simCb()->setFacilityLockForAppResponse(toAidl(info), retry);
     return {};
 }
 
 Return<void> RadioResponse::setSimCardPowerResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setSimCardPowerResponse(toAidl(info));
+    simCb()->setSimCardPowerResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSimCardPowerResponse_1_1(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setSimCardPowerResponse(toAidl(info));
+    simCb()->setSimCardPowerResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSimCardPowerResponse_1_6(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setSimCardPowerResponse(toAidl(info));
+    simCb()->setSimCardPowerResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setUiccSubscriptionResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setUiccSubscriptionResponse(toAidl(info));
+    simCb()->setUiccSubscriptionResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::supplyIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
                                                         int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->supplyIccPin2ForAppResponse(toAidl(info), remainingRetries);
+    simCb()->supplyIccPin2ForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
 Return<void> RadioResponse::supplyIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
                                                        int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->supplyIccPinForAppResponse(toAidl(info), remainingRetries);
+    simCb()->supplyIccPinForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
 Return<void> RadioResponse::supplyIccPuk2ForAppResponse(const V1_0::RadioResponseInfo& info,
                                                         int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->supplyIccPuk2ForAppResponse(toAidl(info), remainingRetries);
+    simCb()->supplyIccPuk2ForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
 Return<void> RadioResponse::supplyIccPukForAppResponse(const V1_0::RadioResponseInfo& info,
                                                        int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->supplyIccPukForAppResponse(toAidl(info), remainingRetries);
+    simCb()->supplyIccPukForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
@@ -350,16 +314,14 @@
                                                                V1_5::PersoSubstate persoType,
                                                                int32_t rRet) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->supplySimDepersonalizationResponse(toAidl(info), aidl::PersoSubstate(persoType), rRet);
+    simCb()->supplySimDepersonalizationResponse(toAidl(info), aidl::PersoSubstate(persoType), rRet);
     return {};
 }
 
 Return<void> RadioResponse::updateSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info,
                                                               int32_t updatedRecordIndex) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->updateSimPhonebookRecordsResponse(toAidl(info), updatedRecordIndex);
+    simCb()->updateSimPhonebookRecordsResponse(toAidl(info), updatedRecordIndex);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
index ca27918..b43f64f 100644
--- a/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
+++ b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
@@ -30,6 +30,10 @@
 namespace aidl = ::aidl::android::hardware::radio::sim;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioSimResponse> RadioSim::respond() {
+    return mCallbackManager->response().simCb();
+}
+
 ScopedAStatus RadioSim::areUiccApplicationsEnabled(int32_t serial) {
     LOG_CALL << serial;
     mHal1_5->areUiccApplicationsEnabled(serial);
@@ -58,7 +62,7 @@
 
 ScopedAStatus RadioSim::getAllowedCarriers(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getAllowedCarriers(serial);
+    mHal1_5->getAllowedCarriers_1_4(serial);
     return ok();
 }
 
@@ -99,7 +103,7 @@
     if (mHal1_6) {
         mHal1_6->getSimPhonebookCapacity(serial);
     } else {
-        respond().getSimPhonebookCapacityResponse(notSupported(serial), {});
+        respond()->getSimPhonebookCapacityResponse(notSupported(serial), {});
     }
     return ok();
 }
@@ -109,7 +113,7 @@
     if (mHal1_6) {
         mHal1_6->getSimPhonebookRecords(serial);
     } else {
-        respond().getSimPhonebookRecordsResponse(notSupported(serial));
+        respond()->getSimPhonebookRecordsResponse(notSupported(serial));
     }
     return ok();
 }
@@ -217,16 +221,10 @@
 }
 
 ScopedAStatus RadioSim::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioSimResponse>& simResponse,
-        const std::shared_ptr<aidl::IRadioSimIndication>& simIndication) {
-    LOG_CALL << simResponse << ' ' << simIndication;
-
-    CHECK(simResponse);
-    CHECK(simIndication);
-
-    mRadioResponse->setResponseFunction(simResponse);
-    mRadioIndication->setResponseFunction(simIndication);
-
+        const std::shared_ptr<aidl::IRadioSimResponse>& response,
+        const std::shared_ptr<aidl::IRadioSimIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
@@ -287,7 +285,7 @@
     if (mHal1_6) {
         mHal1_6->updateSimPhonebookRecords(serial, toHidl(recordInfo));
     } else {
-        respond().updateSimPhonebookRecordsResponse(notSupported(serial), 0);
+        respond()->updateSimPhonebookRecordsResponse(notSupported(serial), 0);
     }
     return ok();
 }
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
index 6d9bda8..359fce0 100644
--- a/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
+++ b/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
@@ -29,113 +29,102 @@
 namespace aidl = ::aidl::android::hardware::radio::voice;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioVoiceIndication> voiceCb) {
-    CHECK(voiceCb);
     mVoiceCb = voiceCb;
 }
 
+std::shared_ptr<aidl::IRadioVoiceIndication> RadioIndication::voiceCb() {
+    return mVoiceCb.get();
+}
+
 Return<void> RadioIndication::callRing(V1_0::RadioIndicationType type, bool isGsm,
                                        const V1_0::CdmaSignalInfoRecord& record) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->callRing(toAidl(type), isGsm, toAidl(record));
+    voiceCb()->callRing(toAidl(type), isGsm, toAidl(record));
     return {};
 }
 
 Return<void> RadioIndication::callStateChanged(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->callStateChanged(toAidl(type));
+    voiceCb()->callStateChanged(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::cdmaCallWaiting(V1_0::RadioIndicationType type,
                                               const V1_0::CdmaCallWaiting& callWaitingRecord) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->cdmaCallWaiting(toAidl(type), toAidl(callWaitingRecord));
+    voiceCb()->cdmaCallWaiting(toAidl(type), toAidl(callWaitingRecord));
     return {};
 }
 
 Return<void> RadioIndication::cdmaInfoRec(V1_0::RadioIndicationType type,
                                           const V1_0::CdmaInformationRecords& records) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->cdmaInfoRec(toAidl(type), toAidl(records.infoRec));
+    voiceCb()->cdmaInfoRec(toAidl(type), toAidl(records.infoRec));
     return {};
 }
 
 Return<void> RadioIndication::cdmaOtaProvisionStatus(V1_0::RadioIndicationType type,
                                                      V1_0::CdmaOtaProvisionStatus status) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->cdmaOtaProvisionStatus(toAidl(type), aidl::CdmaOtaProvisionStatus(status));
+    voiceCb()->cdmaOtaProvisionStatus(toAidl(type), aidl::CdmaOtaProvisionStatus(status));
     return {};
 }
 
 Return<void> RadioIndication::currentEmergencyNumberList(
         V1_0::RadioIndicationType type, const hidl_vec<V1_4::EmergencyNumber>& emergencyNumbers) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->currentEmergencyNumberList(toAidl(type), toAidl(emergencyNumbers));
+    voiceCb()->currentEmergencyNumberList(toAidl(type), toAidl(emergencyNumbers));
     return {};
 }
 
 Return<void> RadioIndication::enterEmergencyCallbackMode(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->enterEmergencyCallbackMode(toAidl(type));
+    voiceCb()->enterEmergencyCallbackMode(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::exitEmergencyCallbackMode(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->exitEmergencyCallbackMode(toAidl(type));
+    voiceCb()->exitEmergencyCallbackMode(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::indicateRingbackTone(V1_0::RadioIndicationType type, bool start) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->indicateRingbackTone(toAidl(type), start);
+    voiceCb()->indicateRingbackTone(toAidl(type), start);
     return {};
 }
 
 Return<void> RadioIndication::onSupplementaryServiceIndication(V1_0::RadioIndicationType type,
                                                                const V1_0::StkCcUnsolSsResult& ss) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->onSupplementaryServiceIndication(toAidl(type), toAidl(ss));
+    voiceCb()->onSupplementaryServiceIndication(toAidl(type), toAidl(ss));
     return {};
 }
 
 Return<void> RadioIndication::resendIncallMute(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->resendIncallMute(toAidl(type));
+    voiceCb()->resendIncallMute(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::srvccStateNotify(V1_0::RadioIndicationType type,
                                                V1_0::SrvccState state) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->srvccStateNotify(toAidl(type), aidl::SrvccState(state));
+    voiceCb()->srvccStateNotify(toAidl(type), aidl::SrvccState(state));
     return {};
 }
 
 Return<void> RadioIndication::stkCallControlAlphaNotify(V1_0::RadioIndicationType type,
                                                         const hidl_string& alpha) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->stkCallControlAlphaNotify(toAidl(type), alpha);
+    voiceCb()->stkCallControlAlphaNotify(toAidl(type), alpha);
     return {};
 }
 
 Return<void> RadioIndication::stkCallSetup(V1_0::RadioIndicationType type, int64_t timeout) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->stkCallSetup(toAidl(type), timeout);
+    voiceCb()->stkCallSetup(toAidl(type), timeout);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
index 0a64c56..d233548 100644
--- a/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
+++ b/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
@@ -29,265 +29,233 @@
 namespace aidl = ::aidl::android::hardware::radio::voice;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioVoiceResponse> voiceCb) {
-    CHECK(voiceCb);
     mVoiceCb = voiceCb;
 }
 
+std::shared_ptr<aidl::IRadioVoiceResponse> RadioResponse::voiceCb() {
+    return mVoiceCb.get();
+}
+
 Return<void> RadioResponse::acceptCallResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->acceptCallResponse(toAidl(info));
+    voiceCb()->acceptCallResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::conferenceResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->conferenceResponse(toAidl(info));
+    voiceCb()->conferenceResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::dialResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->dialResponse(toAidl(info));
+    voiceCb()->dialResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::emergencyDialResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->emergencyDialResponse(toAidl(info));
+    voiceCb()->emergencyDialResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::exitEmergencyCallbackModeResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->exitEmergencyCallbackModeResponse(toAidl(info));
+    voiceCb()->exitEmergencyCallbackModeResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::explicitCallTransferResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->explicitCallTransferResponse(toAidl(info));
+    voiceCb()->explicitCallTransferResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::getCallForwardStatusResponse(
         const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::CallForwardInfo>& callFwdInfos) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getCallForwardStatusResponse(toAidl(info), toAidl(callFwdInfos));
+    voiceCb()->getCallForwardStatusResponse(toAidl(info), toAidl(callFwdInfos));
     return {};
 }
 
 Return<void> RadioResponse::getCallWaitingResponse(const V1_0::RadioResponseInfo& info, bool enable,
                                                    int32_t serviceClass) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getCallWaitingResponse(toAidl(info), enable, serviceClass);
+    voiceCb()->getCallWaitingResponse(toAidl(info), enable, serviceClass);
     return {};
 }
 
 Return<void> RadioResponse::getClipResponse(const V1_0::RadioResponseInfo& info,
                                             V1_0::ClipStatus status) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getClipResponse(toAidl(info), aidl::ClipStatus(status));
+    voiceCb()->getClipResponse(toAidl(info), aidl::ClipStatus(status));
     return {};
 }
 
 Return<void> RadioResponse::getClirResponse(const V1_0::RadioResponseInfo& info, int32_t n,
                                             int32_t m) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getClirResponse(toAidl(info), n, m);
+    voiceCb()->getClirResponse(toAidl(info), n, m);
     return {};
 }
 
 Return<void> RadioResponse::getCurrentCallsResponse(const V1_0::RadioResponseInfo& info,
                                                     const hidl_vec<V1_0::Call>& calls) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
     return {};
 }
 
 Return<void> RadioResponse::getCurrentCallsResponse_1_2(const V1_0::RadioResponseInfo& info,
                                                         const hidl_vec<V1_2::Call>& calls) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
     return {};
 }
 
 Return<void> RadioResponse::getCurrentCallsResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                         const hidl_vec<V1_6::Call>& calls) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
     return {};
 }
 
 Return<void> RadioResponse::getLastCallFailCauseResponse(
         const V1_0::RadioResponseInfo& info, const V1_0::LastCallFailCauseInfo& failCauseinfo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getLastCallFailCauseResponse(toAidl(info), toAidl(failCauseinfo));
+    voiceCb()->getLastCallFailCauseResponse(toAidl(info), toAidl(failCauseinfo));
     return {};
 }
 
 Return<void> RadioResponse::getMuteResponse(const V1_0::RadioResponseInfo& info, bool enable) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getMuteResponse(toAidl(info), enable);
+    voiceCb()->getMuteResponse(toAidl(info), enable);
     return {};
 }
 
 Return<void> RadioResponse::getPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info,
                                                              bool enable) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getPreferredVoicePrivacyResponse(toAidl(info), enable);
+    voiceCb()->getPreferredVoicePrivacyResponse(toAidl(info), enable);
     return {};
 }
 
 Return<void> RadioResponse::getTTYModeResponse(const V1_0::RadioResponseInfo& info,
                                                V1_0::TtyMode mode) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getTtyModeResponse(toAidl(info), aidl::TtyMode(mode));
+    voiceCb()->getTtyModeResponse(toAidl(info), aidl::TtyMode(mode));
     return {};
 }
 
 Return<void> RadioResponse::handleStkCallSetupRequestFromSimResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->handleStkCallSetupRequestFromSimResponse(toAidl(info));
+    voiceCb()->handleStkCallSetupRequestFromSimResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::hangupConnectionResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->hangupConnectionResponse(toAidl(info));
+    voiceCb()->hangupConnectionResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::hangupForegroundResumeBackgroundResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->hangupForegroundResumeBackgroundResponse(toAidl(info));
+    voiceCb()->hangupForegroundResumeBackgroundResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::hangupWaitingOrBackgroundResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->hangupWaitingOrBackgroundResponse(toAidl(info));
+    voiceCb()->hangupWaitingOrBackgroundResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::rejectCallResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->rejectCallResponse(toAidl(info));
+    voiceCb()->rejectCallResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::sendBurstDtmfResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->sendBurstDtmfResponse(toAidl(info));
+    voiceCb()->sendBurstDtmfResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::sendCDMAFeatureCodeResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->sendCdmaFeatureCodeResponse(toAidl(info));
+    voiceCb()->sendCdmaFeatureCodeResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::sendDtmfResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->sendDtmfResponse(toAidl(info));
+    voiceCb()->sendDtmfResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::separateConnectionResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->separateConnectionResponse(toAidl(info));
+    voiceCb()->separateConnectionResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCallForwardResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setCallForwardResponse(toAidl(info));
+    voiceCb()->setCallForwardResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCallWaitingResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setCallWaitingResponse(toAidl(info));
+    voiceCb()->setCallWaitingResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setClirResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setClirResponse(toAidl(info));
+    voiceCb()->setClirResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setMuteResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setMuteResponse(toAidl(info));
+    voiceCb()->setMuteResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setPreferredVoicePrivacyResponse(toAidl(info));
+    voiceCb()->setPreferredVoicePrivacyResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setTTYModeResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setTtyModeResponse(toAidl(info));
+    voiceCb()->setTtyModeResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::startDtmfResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->startDtmfResponse(toAidl(info));
+    voiceCb()->startDtmfResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::stopDtmfResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->stopDtmfResponse(toAidl(info));
+    voiceCb()->stopDtmfResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::switchWaitingOrHoldingAndActiveResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->switchWaitingOrHoldingAndActiveResponse(toAidl(info));
+    voiceCb()->switchWaitingOrHoldingAndActiveResponse(toAidl(info));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
index 16c6b14..7b1d1fa 100644
--- a/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
+++ b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
@@ -30,6 +30,10 @@
 namespace aidl = ::aidl::android::hardware::radio::voice;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioVoiceResponse> RadioVoice::respond() {
+    return mCallbackManager->response().voiceCb();
+}
+
 ScopedAStatus RadioVoice::acceptCall(int32_t serial) {
     LOG_CALL << serial;
     mHal1_5->acceptCall(serial);
@@ -49,13 +53,19 @@
 }
 
 ScopedAStatus RadioVoice::emergencyDial(  //
-        int32_t serial, const aidl::Dial& dialInfo, aidl::EmergencyServiceCategory categories,
+        int32_t serial, const aidl::Dial& info, aidl::EmergencyServiceCategory categories,
         const std::vector<std::string>& urns, aidl::EmergencyCallRouting routing,
-        bool hasKnownUserIntentEmerg, bool isTesting) {
+        bool knownUserIntentEmerg, bool isTesting) {
     LOG_CALL << serial;
-    mHal1_5->emergencyDial(serial, toHidl(dialInfo),
-                           toHidlBitfield<V1_4::EmergencyServiceCategory>(categories), toHidl(urns),
-                           V1_4::EmergencyCallRouting(routing), hasKnownUserIntentEmerg, isTesting);
+    if (mHal1_6) {
+        mHal1_6->emergencyDial_1_6(  //
+                serial, toHidl(info), toHidlBitfield<V1_4::EmergencyServiceCategory>(categories),
+                toHidl(urns), V1_4::EmergencyCallRouting(routing), knownUserIntentEmerg, isTesting);
+    } else {
+        mHal1_5->emergencyDial(  //
+                serial, toHidl(info), toHidlBitfield<V1_4::EmergencyServiceCategory>(categories),
+                toHidl(urns), V1_4::EmergencyCallRouting(routing), knownUserIntentEmerg, isTesting);
+    }
     return ok();
 }
 
@@ -98,7 +108,11 @@
 
 ScopedAStatus RadioVoice::getCurrentCalls(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getCurrentCalls(serial);
+    if (mHal1_6) {
+        mHal1_6->getCurrentCalls_1_6(serial);
+    } else {
+        mHal1_5->getCurrentCalls(serial);
+    }
     return ok();
 }
 
@@ -152,7 +166,7 @@
 
 ScopedAStatus RadioVoice::isVoNrEnabled(int32_t serial) {
     LOG_CALL << serial;
-    // TODO(b/203699028): can't call isVoNrEnabledResponse with 1.6 callback
+    respond()->isVoNrEnabledResponse(notSupported(serial), false);
     return ok();
 }
 
@@ -224,16 +238,10 @@
 }
 
 ScopedAStatus RadioVoice::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioVoiceResponse>& voiceResponse,
-        const std::shared_ptr<aidl::IRadioVoiceIndication>& voiceIndication) {
-    LOG_CALL << voiceResponse << ' ' << voiceIndication;
-
-    CHECK(voiceResponse);
-    CHECK(voiceIndication);
-
-    mRadioResponse->setResponseFunction(voiceResponse);
-    mRadioIndication->setResponseFunction(voiceIndication);
-
+        const std::shared_ptr<aidl::IRadioVoiceResponse>& response,
+        const std::shared_ptr<aidl::IRadioVoiceIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
@@ -245,7 +253,8 @@
 
 ndk::ScopedAStatus RadioVoice::setVoNrEnabled(int32_t serial, [[maybe_unused]] bool enable) {
     LOG_CALL << serial;
-    // TODO(b/203699028): should set `persist.radio.is_vonr_enabled_` property instead
+    // Note: a workaround for older HALs could also be setting persist.radio.is_vonr_enabled_
+    respond()->setVoNrEnabledResponse(notSupported(serial));
     return ok();
 }
 
diff --git a/radio/aidl/compat/service/service.cpp b/radio/aidl/compat/service/service.cpp
index 6bcd4b0..8af05de 100644
--- a/radio/aidl/compat/service/service.cpp
+++ b/radio/aidl/compat/service/service.cpp
@@ -19,13 +19,12 @@
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
+#include <libradiocompat/CallbackManager.h>
 #include <libradiocompat/RadioConfig.h>
 #include <libradiocompat/RadioData.h>
-#include <libradiocompat/RadioIndication.h>
 #include <libradiocompat/RadioMessaging.h>
 #include <libradiocompat/RadioModem.h>
 #include <libradiocompat/RadioNetwork.h>
-#include <libradiocompat/RadioResponse.h>
 #include <libradiocompat/RadioSim.h>
 #include <libradiocompat/RadioVoice.h>
 
@@ -36,9 +35,8 @@
 static std::vector<std::shared_ptr<ndk::ICInterface>> gPublishedHals;
 
 template <typename T>
-static void publishRadioHal(std::shared_ptr<compat::DriverContext> context,
-                            sp<V1_5::IRadio> hidlHal, sp<compat::RadioResponse> responseCb,
-                            sp<compat::RadioIndication> indicationCb, const std::string& slot) {
+static void publishRadioHal(std::shared_ptr<compat::DriverContext> ctx, sp<V1_5::IRadio> hidlHal,
+                            std::shared_ptr<compat::CallbackManager> cm, const std::string& slot) {
     const auto instance = T::descriptor + "/"s + slot;
     if (!AServiceManager_isDeclared(instance.c_str())) {
         LOG(INFO) << instance << " is not declared in VINTF (this may be intentional)";
@@ -46,7 +44,7 @@
     }
     LOG(DEBUG) << "Publishing " << instance;
 
-    auto aidlHal = ndk::SharedRefBase::make<T>(context, hidlHal, responseCb, indicationCb);
+    auto aidlHal = ndk::SharedRefBase::make<T>(ctx, hidlHal, cm);
     gPublishedHals.push_back(aidlHal);
     const auto status = AServiceManager_addService(aidlHal->asBinder().get(), instance.c_str());
     CHECK_EQ(status, STATUS_OK);
@@ -59,17 +57,14 @@
     hidl_utils::linkDeathToDeath(radioHidl);
 
     auto context = std::make_shared<compat::DriverContext>();
+    auto callbackMgr = std::make_shared<compat::CallbackManager>(context, radioHidl);
 
-    auto responseCb = sp<compat::RadioResponse>::make(context);
-    auto indicationCb = sp<compat::RadioIndication>::make(context);
-    radioHidl->setResponseFunctions(responseCb, indicationCb).assertOk();
-
-    publishRadioHal<compat::RadioData>(context, radioHidl, responseCb, indicationCb, slot);
-    publishRadioHal<compat::RadioMessaging>(context, radioHidl, responseCb, indicationCb, slot);
-    publishRadioHal<compat::RadioModem>(context, radioHidl, responseCb, indicationCb, slot);
-    publishRadioHal<compat::RadioNetwork>(context, radioHidl, responseCb, indicationCb, slot);
-    publishRadioHal<compat::RadioSim>(context, radioHidl, responseCb, indicationCb, slot);
-    publishRadioHal<compat::RadioVoice>(context, radioHidl, responseCb, indicationCb, slot);
+    publishRadioHal<compat::RadioData>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioMessaging>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioModem>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioNetwork>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioSim>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioVoice>(context, radioHidl, callbackMgr, slot);
 }
 
 static void publishRadioConfig() {
@@ -86,6 +81,7 @@
 }
 
 static void main() {
+    base::InitLogging(nullptr, base::LogdLogger(base::RADIO));
     base::SetDefaultTag("radiocompat");
     base::SetMinimumLogSeverity(base::VERBOSE);
     LOG(DEBUG) << "Radio HAL compat service starting...";
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
new file mode 100644
index 0000000..935d2e5
--- /dev/null
+++ b/radio/aidl/vts/Android.bp
@@ -0,0 +1,71 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalRadioTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "radio_aidl_hal_utils.cpp",
+        "radio_data_indication.cpp",
+        "radio_data_response.cpp",
+        "radio_data_test.cpp",
+        "radio_messaging_indication.cpp",
+        "radio_messaging_response.cpp",
+        "radio_messaging_test.cpp",
+        "radio_modem_indication.cpp",
+        "radio_modem_response.cpp",
+        "radio_modem_test.cpp",
+        "radio_network_indication.cpp",
+        "radio_network_response.cpp",
+        "radio_network_test.cpp",
+        "radio_sim_indication.cpp",
+        "radio_sim_response.cpp",
+        "radio_sim_test.cpp",
+        "radio_voice_indication.cpp",
+        "radio_voice_response.cpp",
+        "radio_voice_test.cpp",
+        "VtsHalRadioTargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libvintf",
+    ],
+    static_libs: [
+        "android.hardware.radio-V1-ndk",
+        "android.hardware.radio.config-V1-ndk",
+        "android.hardware.radio.data-V1-ndk",
+        "android.hardware.radio.messaging-V1-ndk",
+        "android.hardware.radio.modem-V1-ndk",
+        "android.hardware.radio.network-V1-ndk",
+        "android.hardware.radio.sim-V1-ndk",
+        "android.hardware.radio.voice-V1-ndk",
+    ],
+    // TODO(b/210712359): enable after b/207695009 is resolved.
+    //test_suites: [
+    //    "general-tests",
+    //    "vts",
+    //],
+}
diff --git a/radio/aidl/vts/VtsHalRadioTargetTest.cpp b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
new file mode 100644
index 0000000..e829f8e
--- /dev/null
+++ b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_process.h>
+
+#include "radio_data_utils.h"
+#include "radio_messaging_utils.h"
+#include "radio_modem_utils.h"
+#include "radio_network_utils.h"
+#include "radio_sim_utils.h"
+#include "radio_voice_utils.h"
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioDataTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioDataTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioData::descriptor)),
+        android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioMessagingTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioMessagingTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioMessaging::descriptor)),
+        android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioModemTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioModemTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioModem::descriptor)),
+        android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioNetworkTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioNetworkTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioNetwork::descriptor)),
+        android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioSimTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, RadioSimTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IRadioSim::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioVoiceTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioVoiceTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioVoice::descriptor)),
+        android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.cpp b/radio/aidl/vts/radio_aidl_hal_utils.cpp
new file mode 100644
index 0000000..14a16c0
--- /dev/null
+++ b/radio/aidl/vts/radio_aidl_hal_utils.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "RadioTest"
+
+#include "radio_aidl_hal_utils.h"
+#include <iostream>
+#include "VtsCoreUtil.h"
+
+using namespace aidl::android::hardware::radio::network;
+
+#define WAIT_TIMEOUT_PERIOD 75
+
+aidl::android::hardware::radio::sim::CardStatus cardStatus = {};
+
+int GetRandomSerialNumber() {
+    return rand();
+}
+
+::testing::AssertionResult CheckAnyOfErrors(RadioError err, std::vector<RadioError> errors,
+                                            CheckFlag flag) {
+    const static std::vector<RadioError> generalErrors = {
+            RadioError::RADIO_NOT_AVAILABLE,   RadioError::NO_MEMORY,
+            RadioError::INTERNAL_ERR,          RadioError::SYSTEM_ERR,
+            RadioError::REQUEST_NOT_SUPPORTED, RadioError::CANCELLED};
+    if (flag == CHECK_GENERAL_ERROR || flag == CHECK_OEM_AND_GENERAL_ERROR) {
+        for (size_t i = 0; i < generalErrors.size(); i++) {
+            if (err == generalErrors[i]) {
+                return testing::AssertionSuccess();
+            }
+        }
+    }
+    if (flag == CHECK_OEM_ERROR || flag == CHECK_OEM_AND_GENERAL_ERROR) {
+        if (err >= RadioError::OEM_ERROR_1 && err <= RadioError::OEM_ERROR_25) {
+            return testing::AssertionSuccess();
+        }
+    }
+    for (size_t i = 0; i < errors.size(); i++) {
+        if (err == errors[i]) {
+            return testing::AssertionSuccess();
+        }
+    }
+    return testing::AssertionFailure() << "RadioError:" + toString(err) + " is returned";
+}
+
+// Runs "pm list features" and attempts to find the specified feature in its output.
+bool deviceSupportsFeature(const char* feature) {
+    bool hasFeature = false;
+    FILE* p = popen("/system/bin/pm list features", "re");
+    if (p) {
+        char* line = NULL;
+        size_t len = 0;
+        while (getline(&line, &len, p) > 0) {
+            if (strstr(line, feature)) {
+                hasFeature = true;
+                break;
+            }
+        }
+        pclose(p);
+    } else {
+        __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, "popen failed: %d", errno);
+        _exit(EXIT_FAILURE);
+    }
+    __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "Feature %s: %ssupported", feature,
+                        hasFeature ? "" : "not ");
+    return hasFeature;
+}
+
+bool isSsSsEnabled() {
+    // Do not use checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "")
+    // until b/148904287 is fixed. We need exact matching instead of partial matching. (i.e.
+    // by definition the empty string "" is a substring of any string).
+    return !isDsDsEnabled() && !isTsTsEnabled();
+}
+
+bool isDsDsEnabled() {
+    return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "dsds");
+}
+
+bool isTsTsEnabled() {
+    return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "tsts");
+}
+
+bool isVoiceInService(RegState state) {
+    return RegState::REG_HOME == state || RegState::REG_ROAMING == state;
+}
+
+bool isVoiceEmergencyOnly(RegState state) {
+    return RegState::NOT_REG_MT_NOT_SEARCHING_OP_EM == state ||
+           RegState::NOT_REG_MT_SEARCHING_OP_EM == state || RegState::REG_DENIED_EM == state ||
+           RegState::UNKNOWN_EM == state;
+}
+
+bool isServiceValidForDeviceConfiguration(std::string& serviceName) {
+    if (isSsSsEnabled()) {
+        // Device is configured as SSSS.
+        if (serviceName != RADIO_SERVICE_SLOT1_NAME) {
+            ALOGI("%s instance is not valid for SSSS device.", serviceName.c_str());
+            return false;
+        }
+    } else if (isDsDsEnabled()) {
+        // Device is configured as DSDS.
+        if (serviceName != RADIO_SERVICE_SLOT1_NAME && serviceName != RADIO_SERVICE_SLOT2_NAME) {
+            ALOGI("%s instance is not valid for DSDS device.", serviceName.c_str());
+            return false;
+        }
+    } else if (isTsTsEnabled()) {
+        // Device is configured as TSTS.
+        if (serviceName != RADIO_SERVICE_SLOT1_NAME && serviceName != RADIO_SERVICE_SLOT2_NAME &&
+            serviceName != RADIO_SERVICE_SLOT3_NAME) {
+            ALOGI("%s instance is not valid for TSTS device.", serviceName.c_str());
+            return false;
+        }
+    }
+    return true;
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioResponseWaiter::notify(int receivedSerial) {
+    std::unique_lock<std::mutex> lock(mtx_);
+    if (serial == receivedSerial) {
+        count_++;
+        cv_.notify_one();
+    }
+}
+
+/*
+ * Wait till the response message is notified or till WAIT_TIMEOUT_PERIOD.
+ */
+std::cv_status RadioResponseWaiter::wait() {
+    std::unique_lock<std::mutex> lock(mtx_);
+    std::cv_status status = std::cv_status::no_timeout;
+    auto now = std::chrono::system_clock::now();
+    while (count_ == 0) {
+        status = cv_.wait_until(lock, now + std::chrono::seconds(WAIT_TIMEOUT_PERIOD));
+        if (status == std::cv_status::timeout) {
+            return status;
+        }
+    }
+    count_--;
+    return status;
+}
+
+/**
+ * Specific features on the Radio HAL rely on Radio HAL Capabilities.
+ * The VTS test related to those features must not run if the related capability is disabled.
+ * Typical usage within VTS: if (getRadioHalCapabilities()) return;
+ */
+bool RadioResponseWaiter::getRadioHalCapabilities() {
+    // TODO(b/210712359): implement after RadioConfig VTS is created
+    /**
+    // Get HalDeviceCapabilities from the radio config
+    std::shared_ptr<RadioConfigResponse> radioConfigRsp = new (std::nothrow)
+    RadioConfigResponse(*this); radioConfig->setResponseFunctions(radioConfigRsp, nullptr); serial =
+    GetRandomSerialNumber();
+
+    radioConfig->getHalDeviceCapabilities(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    return radioConfigRsp->modemReducedFeatureSet1;
+    **/
+    return true;
+}
\ No newline at end of file
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.h b/radio/aidl/vts/radio_aidl_hal_utils.h
new file mode 100644
index 0000000..2f31fa8
--- /dev/null
+++ b/radio/aidl/vts/radio_aidl_hal_utils.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/radio/RadioError.h>
+#include <aidl/android/hardware/radio/network/RegState.h>
+#include <aidl/android/hardware/radio/sim/CardStatus.h>
+#include <utils/Log.h>
+#include <vector>
+
+using namespace aidl::android::hardware::radio;
+using aidl::android::hardware::radio::sim::CardStatus;
+
+extern CardStatus cardStatus;
+
+/*
+ * MACRO used to skip test case when radio response return error REQUEST_NOT_SUPPORTED
+ * on HAL versions which has deprecated the request interfaces. The MACRO can only be used
+ * AFTER receiving radio response.
+ */
+#define SKIP_TEST_IF_REQUEST_NOT_SUPPORTED_WITH_HAL(__ver__, __radio__, __radioRsp__)      \
+    do {                                                                                   \
+        sp<::android::hardware::radio::V##__ver__::IRadio> __radio =                       \
+                ::android::hardware::radio::V##__ver__::IRadio::castFrom(__radio__);       \
+        if (__radio && __radioRsp__->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED) { \
+            GTEST_SKIP() << "REQUEST_NOT_SUPPORTED";                                       \
+        }                                                                                  \
+    } while (0)
+
+enum CheckFlag {
+    CHECK_DEFAULT = 0,
+    CHECK_GENERAL_ERROR = 1,
+    CHECK_OEM_ERROR = 2,
+    CHECK_OEM_AND_GENERAL_ERROR = 3,
+    CHECK_SAP_ERROR = 4,
+};
+
+static constexpr const char* FEATURE_VOICE_CALL = "android.software.connectionservice";
+
+static constexpr const char* FEATURE_TELEPHONY = "android.hardware.telephony";
+
+static constexpr const char* FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
+
+static constexpr const char* FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
+
+#define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
+#define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
+#define MODEM_SET_SIM_POWER_DELAY_IN_SECONDS 2
+
+#define RADIO_SERVICE_SLOT1_NAME "slot1"  // HAL instance name for SIM slot 1 or single SIM device
+#define RADIO_SERVICE_SLOT2_NAME "slot2"  // HAL instance name for SIM slot 2 on dual SIM device
+#define RADIO_SERVICE_SLOT3_NAME "slot3"  // HAL instance name for SIM slot 3 on triple SIM device
+
+/*
+ * Generate random serial number for radio test
+ */
+int GetRandomSerialNumber();
+
+/*
+ * Check multiple radio error codes which are possibly returned because of the different
+ * vendor/devices implementations. It allows optional checks for general errors or/and oem errors.
+ */
+::testing::AssertionResult CheckAnyOfErrors(RadioError err, std::vector<RadioError> generalError,
+                                            CheckFlag flag = CHECK_DEFAULT);
+
+/*
+ * Check if device supports feature.
+ */
+bool deviceSupportsFeature(const char* feature);
+
+/*
+ * Check if device is in SsSs (Single SIM Single Standby).
+ */
+bool isSsSsEnabled();
+
+/*
+ * Check if device is in DSDS (Dual SIM Dual Standby).
+ */
+bool isDsDsEnabled();
+
+/*
+ * Check if device is in TSTS (Triple SIM Triple Standby).
+ */
+bool isTsTsEnabled();
+
+/*
+ * Check if voice status is in emergency only.
+ */
+bool isVoiceEmergencyOnly(aidl::android::hardware::radio::network::RegState state);
+
+/*
+ * Check if voice status is in service.
+ */
+bool isVoiceInService(aidl::android::hardware::radio::network::RegState state);
+
+/*
+ * Check if service is valid for device configuration
+ */
+bool isServiceValidForDeviceConfiguration(std::string& serviceName);
+
+/**
+ * Used when waiting for an asynchronous response from the HAL.
+ */
+class RadioResponseWaiter {
+  protected:
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    int count_;
+
+  public:
+    /* Serial number for radio request */
+    int serial;
+
+    /* Used as a mechanism to inform the test about data/event callback */
+    void notify(int receivedSerial);
+
+    /* Test code calls this function to wait for response */
+    std::cv_status wait();
+
+    // TODO(b/210712359): this probably isn't the best place to put this, but it works for now
+    //  since all RadioXTest extend RadioResponseWaiter
+    /* Used to get the radio HAL capabilities */
+    bool getRadioHalCapabilities();
+};
diff --git a/radio/aidl/vts/radio_data_indication.cpp b/radio/aidl/vts/radio_data_indication.cpp
new file mode 100644
index 0000000..1e02fe1
--- /dev/null
+++ b/radio/aidl/vts/radio_data_indication.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_data_utils.h"
+
+RadioDataIndication::RadioDataIndication(RadioDataTest& parent) : parent_data(parent) {}
+
+ndk::ScopedAStatus RadioDataIndication::dataCallListChanged(
+        RadioIndicationType /*type*/, const std::vector<SetupDataCallResult>& /*dcList*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataIndication::keepaliveStatus(RadioIndicationType /*type*/,
+                                                        const KeepaliveStatus& /*status*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataIndication::pcoData(RadioIndicationType /*type*/,
+                                                const PcoDataInfo& /*pco*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataIndication::unthrottleApn(RadioIndicationType /*type*/,
+                                                      const DataProfileInfo& /*dataProfileInfo*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_data_response.cpp b/radio/aidl/vts/radio_data_response.cpp
new file mode 100644
index 0000000..682ddfb
--- /dev/null
+++ b/radio/aidl/vts/radio_data_response.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_data_utils.h"
+
+RadioDataResponse::RadioDataResponse(RadioResponseWaiter& parent) : parent_data(parent) {}
+
+ndk::ScopedAStatus RadioDataResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::allocatePduSessionIdResponse(const RadioResponseInfo& info,
+                                                                   int32_t id) {
+    rspInfo = info;
+    allocatedPduSessionId = id;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::cancelHandoverResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::deactivateDataCallResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::getDataCallListResponse(
+        const RadioResponseInfo& info, const std::vector<SetupDataCallResult>& /*dcResponse*/) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::getSlicingConfigResponse(
+        const RadioResponseInfo& info, const SlicingConfig& /*slicingConfig*/) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::releasePduSessionIdResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setDataAllowedResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setDataProfileResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setDataThrottlingResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setInitialAttachApnResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setupDataCallResponse(const RadioResponseInfo& info,
+                                                            const SetupDataCallResult& dcResponse) {
+    rspInfo = info;
+    setupDataCallResult = dcResponse;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::startHandoverResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::startKeepaliveResponse(const RadioResponseInfo& /*info*/,
+                                                             const KeepaliveStatus& /*status*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::stopKeepaliveResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_data_test.cpp b/radio/aidl/vts/radio_data_test.cpp
new file mode 100644
index 0000000..dbf0eb7
--- /dev/null
+++ b/radio/aidl/vts/radio_data_test.cpp
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <algorithm>
+
+#include "radio_data_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioDataTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_data = IRadioData::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_data.get());
+
+    radioRsp_data = ndk::SharedRefBase::make<RadioDataResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_data.get());
+
+    count_ = 0;
+
+    radioInd_data = ndk::SharedRefBase::make<RadioDataIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_data.get());
+
+    radio_data->setResponseFunctions(radioRsp_data, radioInd_data);
+
+    // Assert IRadioConfig exists before testing
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
+            aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
+                    ndk::SpAIBinder(AServiceManager_waitForService(
+                            "android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radioConfig.get());
+}
+
+ndk::ScopedAStatus RadioDataTest::getDataCallList() {
+    serial = GetRandomSerialNumber();
+    radio_data->getDataCallList(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    return ndk::ScopedAStatus::ok();
+}
+
+/*
+ * Test IRadioData.setupDataCall() for the response returned.
+ */
+TEST_P(RadioDataTest, setupDataCall) {
+    serial = GetRandomSerialNumber();
+
+    AccessNetwork accessNetwork = AccessNetwork::EUTRAN;
+
+    DataProfileInfo dataProfileInfo;
+    memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+    dataProfileInfo.profileId = DataProfileInfo::ID_DEFAULT;
+    dataProfileInfo.apn = std::string("internet");
+    dataProfileInfo.protocol = PdpProtocolType::IP;
+    dataProfileInfo.roamingProtocol = PdpProtocolType::IP;
+    dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+    dataProfileInfo.user = std::string("username");
+    dataProfileInfo.password = std::string("password");
+    dataProfileInfo.type = DataProfileInfo::TYPE_THREE_GPP;
+    dataProfileInfo.maxConnsTime = 300;
+    dataProfileInfo.maxConns = 20;
+    dataProfileInfo.waitTime = 0;
+    dataProfileInfo.enabled = true;
+    // TODO(b/210712359): 320 was the previous value; need to support bitmaps
+    dataProfileInfo.supportedApnTypesBitmap = ApnTypes::DEFAULT;
+    // TODO(b/210712359): 161543 was the previous value; need to support bitmaps
+    dataProfileInfo.bearerBitmap = RadioAccessFamily::LTE;
+    dataProfileInfo.mtuV4 = 0;
+    dataProfileInfo.mtuV6 = 0;
+    dataProfileInfo.preferred = true;
+    dataProfileInfo.persistent = false;
+
+    bool roamingAllowed = false;
+
+    std::vector<LinkAddress> addresses = {};
+    std::vector<std::string> dnses = {};
+
+    DataRequestReason reason = DataRequestReason::NORMAL;
+    SliceInfo sliceInfo;
+    bool matchAllRuleAllowed = true;
+
+    ndk::ScopedAStatus res =
+            radio_data->setupDataCall(serial, accessNetwork, dataProfileInfo, roamingAllowed,
+                                      reason, addresses, dnses, -1, sliceInfo, matchAllRuleAllowed);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+    }
+}
+
+/*
+ * Test IRadioData.setupDataCall() with osAppId for the response returned.
+ */
+TEST_P(RadioDataTest, setupDataCall_osAppId) {
+    serial = GetRandomSerialNumber();
+
+    AccessNetwork accessNetwork = AccessNetwork::EUTRAN;
+
+    TrafficDescriptor trafficDescriptor;
+    OsAppId osAppId;
+    std::string osAppIdString("osAppId");
+    // TODO(b/210712359): there should be a cleaner way to convert this
+    std::vector<unsigned char> output(osAppIdString.length());
+    std::transform(osAppIdString.begin(), osAppIdString.end(), output.begin(),
+                   [](char c) { return static_cast<unsigned char>(c); });
+    osAppId.osAppId = output;
+    trafficDescriptor.osAppId = osAppId;
+
+    DataProfileInfo dataProfileInfo;
+    memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+    dataProfileInfo.profileId = DataProfileInfo::ID_DEFAULT;
+    dataProfileInfo.apn = std::string("internet");
+    dataProfileInfo.protocol = PdpProtocolType::IP;
+    dataProfileInfo.roamingProtocol = PdpProtocolType::IP;
+    dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+    dataProfileInfo.user = std::string("username");
+    dataProfileInfo.password = std::string("password");
+    dataProfileInfo.type = DataProfileInfo::TYPE_THREE_GPP;
+    dataProfileInfo.maxConnsTime = 300;
+    dataProfileInfo.maxConns = 20;
+    dataProfileInfo.waitTime = 0;
+    dataProfileInfo.enabled = true;
+    // TODO(b/210712359): 320 was the previous value; need to support bitmaps
+    dataProfileInfo.supportedApnTypesBitmap = ApnTypes::DEFAULT;
+    // TODO(b/210712359): 161543 was the previous value; need to support bitmaps
+    dataProfileInfo.bearerBitmap = RadioAccessFamily::LTE;
+    dataProfileInfo.mtuV4 = 0;
+    dataProfileInfo.mtuV6 = 0;
+    dataProfileInfo.preferred = true;
+    dataProfileInfo.persistent = false;
+    dataProfileInfo.trafficDescriptor = trafficDescriptor;
+
+    bool roamingAllowed = false;
+
+    std::vector<LinkAddress> addresses = {};
+    std::vector<std::string> dnses = {};
+
+    DataRequestReason reason = DataRequestReason::NORMAL;
+    SliceInfo sliceInfo;
+    bool matchAllRuleAllowed = true;
+
+    ndk::ScopedAStatus res =
+            radio_data->setupDataCall(serial, accessNetwork, dataProfileInfo, roamingAllowed,
+                                      reason, addresses, dnses, -1, sliceInfo, matchAllRuleAllowed);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+        if (radioRsp_data->setupDataCallResult.trafficDescriptors.size() <= 0) {
+            return;
+        }
+        EXPECT_EQ(trafficDescriptor.osAppId.value().osAppId,
+                  radioRsp_data->setupDataCallResult.trafficDescriptors[0].osAppId.value().osAppId);
+    }
+}
+
+/*
+ * Test IRadioData.getSlicingConfig() for the response returned.
+ */
+TEST_P(RadioDataTest, getSlicingConfig) {
+    serial = GetRandomSerialNumber();
+    radio_data->getSlicingConfig(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::INTERNAL_ERR, RadioError::MODEM_ERR}));
+    }
+}
+
+/*
+ * Test IRadioData.setDataThrottling() for the response returned.
+ */
+TEST_P(RadioDataTest, setDataThrottling) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_data->setDataThrottling(
+            serial, DataThrottlingAction::THROTTLE_SECONDARY_CARRIER, 60000);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+                                      RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+    }
+
+    sleep(1);
+    serial = GetRandomSerialNumber();
+
+    res = radio_data->setDataThrottling(serial, DataThrottlingAction::THROTTLE_ANCHOR_CARRIER,
+                                        60000);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+                                      RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+    }
+
+    sleep(1);
+    serial = GetRandomSerialNumber();
+
+    res = radio_data->setDataThrottling(serial, DataThrottlingAction::HOLD, 60000);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+                                      RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+    }
+
+    sleep(1);
+    serial = GetRandomSerialNumber();
+
+    res = radio_data->setDataThrottling(serial, DataThrottlingAction::NO_DATA_THROTTLING, 60000);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+                                      RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+    }
+
+    sleep(1);
+}
diff --git a/radio/aidl/vts/radio_data_utils.h b/radio/aidl/vts/radio_data_utils.h
new file mode 100644
index 0000000..ada8ac1
--- /dev/null
+++ b/radio/aidl/vts/radio_data_utils.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/data/BnRadioDataIndication.h>
+#include <aidl/android/hardware/radio/data/BnRadioDataResponse.h>
+#include <aidl/android/hardware/radio/data/IRadioData.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::data;
+using aidl::android::hardware::radio::sim::CardStatus;
+
+class RadioDataTest;
+
+/* Callback class for radio data response */
+class RadioDataResponse : public BnRadioDataResponse {
+  protected:
+    RadioResponseWaiter& parent_data;
+
+  public:
+    RadioDataResponse(RadioResponseWaiter& parent_data);
+    virtual ~RadioDataResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    int32_t allocatedPduSessionId;
+    SetupDataCallResult setupDataCallResult;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus allocatePduSessionIdResponse(const RadioResponseInfo& info,
+                                                            int32_t id) override;
+
+    virtual ndk::ScopedAStatus cancelHandoverResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus deactivateDataCallResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getDataCallListResponse(
+            const RadioResponseInfo& info,
+            const std::vector<SetupDataCallResult>& dcResponse) override;
+
+    virtual ndk::ScopedAStatus getSlicingConfigResponse(
+            const RadioResponseInfo& info, const SlicingConfig& slicingConfig) override;
+
+    virtual ndk::ScopedAStatus releasePduSessionIdResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setDataAllowedResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setDataProfileResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setDataThrottlingResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setInitialAttachApnResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setupDataCallResponse(
+            const RadioResponseInfo& info, const SetupDataCallResult& dcResponse) override;
+
+    virtual ndk::ScopedAStatus startHandoverResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus startKeepaliveResponse(const RadioResponseInfo& info,
+                                                      const KeepaliveStatus& status) override;
+
+    virtual ndk::ScopedAStatus stopKeepaliveResponse(const RadioResponseInfo& info) override;
+};
+
+/* Callback class for radio data indication */
+class RadioDataIndication : public BnRadioDataIndication {
+  protected:
+    RadioDataTest& parent_data;
+
+  public:
+    RadioDataIndication(RadioDataTest& parent_data);
+    virtual ~RadioDataIndication() = default;
+
+    virtual ndk::ScopedAStatus dataCallListChanged(
+            RadioIndicationType type, const std::vector<SetupDataCallResult>& dcList) override;
+
+    virtual ndk::ScopedAStatus keepaliveStatus(RadioIndicationType type,
+                                               const KeepaliveStatus& status) override;
+
+    virtual ndk::ScopedAStatus pcoData(RadioIndicationType type, const PcoDataInfo& pco) override;
+
+    virtual ndk::ScopedAStatus unthrottleApn(RadioIndicationType type,
+                                             const DataProfileInfo& dataProfile) override;
+};
+
+// The main test class for Radio AIDL Data.
+class RadioDataTest : public ::testing::TestWithParam<std::string>, public RadioResponseWaiter {
+  protected:
+    /* Get current data call list */
+    ndk::ScopedAStatus getDataCallList();
+
+  public:
+    virtual void SetUp() override;
+
+    /* radio data service handle */
+    std::shared_ptr<IRadioData> radio_data;
+    /* radio data response handle */
+    std::shared_ptr<RadioDataResponse> radioRsp_data;
+    /* radio data indication handle */
+    std::shared_ptr<RadioDataIndication> radioInd_data;
+};
diff --git a/radio/aidl/vts/radio_messaging_indication.cpp b/radio/aidl/vts/radio_messaging_indication.cpp
new file mode 100644
index 0000000..7eeb266
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_indication.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_messaging_utils.h"
+
+RadioMessagingIndication::RadioMessagingIndication(RadioMessagingTest& parent)
+    : parent_messaging(parent) {}
+
+ndk::ScopedAStatus RadioMessagingIndication::cdmaNewSms(RadioIndicationType /*type*/,
+                                                        const CdmaSmsMessage& /*msg*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::cdmaRuimSmsStorageFull(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newBroadcastSms(RadioIndicationType /*type*/,
+                                                             const std::vector<uint8_t>& /*data*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newSms(RadioIndicationType /*type*/,
+                                                    const std::vector<uint8_t>& /*pdu*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newSmsOnSim(RadioIndicationType /*type*/,
+                                                         int32_t /*recordNumber*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newSmsStatusReport(
+        RadioIndicationType /*type*/, const std::vector<uint8_t>& /*pdu*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::onUssd(RadioIndicationType /*type*/,
+                                                    UssdModeType /*modeType*/,
+                                                    const std::string& /*msg*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::simSmsStorageFull(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_messaging_response.cpp b/radio/aidl/vts/radio_messaging_response.cpp
new file mode 100644
index 0000000..d73278f
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_response.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_messaging_utils.h"
+
+RadioMessagingResponse::RadioMessagingResponse(RadioResponseWaiter& parent)
+    : parent_messaging(parent) {}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeIncomingGsmSmsWithPduResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeLastIncomingCdmaSmsResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeLastIncomingGsmSmsResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::cancelPendingUssdResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::deleteSmsOnRuimResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::deleteSmsOnSimResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::getCdmaBroadcastConfigResponse(
+        const RadioResponseInfo& /*info*/,
+        const std::vector<CdmaBroadcastSmsConfigInfo>& /*configs*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::getGsmBroadcastConfigResponse(
+        const RadioResponseInfo& /*info*/,
+        const std::vector<GsmBroadcastSmsConfigInfo>& /*configs*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::getSmscAddressResponse(const RadioResponseInfo& /*info*/,
+                                                                  const std::string& /*smsc*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::reportSmsMemoryStatusResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendCdmaSmsExpectMoreResponse(
+        const RadioResponseInfo& info, const SendSmsResult& sms) {
+    rspInfo = info;
+    sendSmsResult = sms;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendCdmaSmsResponse(const RadioResponseInfo& info,
+                                                               const SendSmsResult& sms) {
+    rspInfo = info;
+    sendSmsResult = sms;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendImsSmsResponse(const RadioResponseInfo& /*info*/,
+                                                              const SendSmsResult& /*sms*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendSmsExpectMoreResponse(const RadioResponseInfo& info,
+                                                                     const SendSmsResult& sms) {
+    rspInfo = info;
+    sendSmsResult = sms;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendSmsResponse(const RadioResponseInfo& info,
+                                                           const SendSmsResult& sms) {
+    rspInfo = info;
+    sendSmsResult = sms;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendUssdResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setCdmaBroadcastActivationResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setCdmaBroadcastConfigResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setGsmBroadcastActivationResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setGsmBroadcastConfigResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setSmscAddressResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::writeSmsToRuimResponse(const RadioResponseInfo& /*info*/,
+                                                                  int32_t /*index*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::writeSmsToSimResponse(const RadioResponseInfo& /*info*/,
+                                                                 int32_t /*index*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_messaging_test.cpp b/radio/aidl/vts/radio_messaging_test.cpp
new file mode 100644
index 0000000..58aeaab
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_test.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_messaging_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioMessagingTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_messaging = IRadioMessaging::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_messaging.get());
+
+    radioRsp_messaging = ndk::SharedRefBase::make<RadioMessagingResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_messaging.get());
+
+    count_ = 0;
+
+    radioInd_messaging = ndk::SharedRefBase::make<RadioMessagingIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_messaging.get());
+
+    radio_messaging->setResponseFunctions(radioRsp_messaging, radioInd_messaging);
+
+    // Assert IRadioConfig exists before testing
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
+            aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
+                    ndk::SpAIBinder(AServiceManager_waitForService(
+                            "android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radioConfig.get());
+}
+
+/*
+ * Test IRadioMessaging.sendSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendSms) {
+    LOG(DEBUG) << "sendSms";
+    serial = GetRandomSerialNumber();
+    GsmSmsMessage msg;
+    msg.smscPdu = "";
+    msg.pdu = "01000b916105770203f3000006d4f29c3e9b01";
+
+    radio_messaging->sendSms(serial, msg);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+        EXPECT_EQ(0, radioRsp_messaging->sendSmsResult.errorCode);
+    }
+    LOG(DEBUG) << "sendSms finished";
+}
+
+/*
+ * Test IRadioMessaging.sendSmsExpectMore() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendSmsExpectMore) {
+    LOG(DEBUG) << "sendSmsExpectMore";
+    serial = GetRandomSerialNumber();
+    GsmSmsMessage msg;
+    msg.smscPdu = "";
+    msg.pdu = "01000b916105770203f3000006d4f29c3e9b01";
+
+    radio_messaging->sendSmsExpectMore(serial, msg);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendSmsExpectMore finished";
+}
+
+/*
+ * Test IRadioMessaging.sendCdmaSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendCdmaSms) {
+    LOG(DEBUG) << "sendCdmaSms";
+    serial = GetRandomSerialNumber();
+
+    // Create a CdmaSmsAddress
+    CdmaSmsAddress cdmaSmsAddress;
+    cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+    cdmaSmsAddress.isNumberModeDataNetwork = false;
+    cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+    cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_UNKNOWN;
+    cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
+
+    // Create a CdmaSmsSubAddress
+    CdmaSmsSubaddress cdmaSmsSubaddress;
+    cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+    cdmaSmsSubaddress.odd = false;
+    cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+    // Create a CdmaSmsMessage
+    CdmaSmsMessage cdmaSmsMessage;
+    cdmaSmsMessage.teleserviceId = 4098;
+    cdmaSmsMessage.isServicePresent = false;
+    cdmaSmsMessage.serviceCategory = 0;
+    cdmaSmsMessage.address = cdmaSmsAddress;
+    cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
+    cdmaSmsMessage.bearerData =
+            (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
+
+    radio_messaging->sendCdmaSms(serial, cdmaSmsMessage);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendCdmaSms finished";
+}
+
+/*
+ * Test IRadioMessaging.sendCdmaSmsExpectMore() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendCdmaSmsExpectMore) {
+    serial = GetRandomSerialNumber();
+
+    // Create a CdmaSmsAddress
+    CdmaSmsAddress cdmaSmsAddress;
+    cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+    cdmaSmsAddress.isNumberModeDataNetwork = false;
+    cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+    cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_UNKNOWN;
+    cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
+
+    // Create a CdmaSmsSubAddress
+    CdmaSmsSubaddress cdmaSmsSubaddress;
+    cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+    cdmaSmsSubaddress.odd = false;
+    cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+    // Create a CdmaSmsMessage
+    CdmaSmsMessage cdmaSmsMessage;
+    cdmaSmsMessage.teleserviceId = 4098;
+    cdmaSmsMessage.isServicePresent = false;
+    cdmaSmsMessage.serviceCategory = 0;
+    cdmaSmsMessage.address = cdmaSmsAddress;
+    cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
+    cdmaSmsMessage.bearerData =
+            (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
+
+    radio_messaging->sendCdmaSmsExpectMore(serial, cdmaSmsMessage);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+}
diff --git a/radio/aidl/vts/radio_messaging_utils.h b/radio/aidl/vts/radio_messaging_utils.h
new file mode 100644
index 0000000..96cde08
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_utils.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/messaging/BnRadioMessagingIndication.h>
+#include <aidl/android/hardware/radio/messaging/BnRadioMessagingResponse.h>
+#include <aidl/android/hardware/radio/messaging/IRadioMessaging.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::messaging;
+
+class RadioMessagingTest;
+
+/* Callback class for radio messaging response */
+class RadioMessagingResponse : public BnRadioMessagingResponse {
+  protected:
+    RadioResponseWaiter& parent_messaging;
+
+  public:
+    RadioMessagingResponse(RadioResponseWaiter& parent_messaging);
+    virtual ~RadioMessagingResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    SendSmsResult sendSmsResult;
+
+    virtual ndk::ScopedAStatus acknowledgeIncomingGsmSmsWithPduResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus acknowledgeLastIncomingCdmaSmsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus acknowledgeLastIncomingGsmSmsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus cancelPendingUssdResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus deleteSmsOnRuimResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus deleteSmsOnSimResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getCdmaBroadcastConfigResponse(
+            const RadioResponseInfo& info,
+            const std::vector<CdmaBroadcastSmsConfigInfo>& configs) override;
+
+    virtual ndk::ScopedAStatus getGsmBroadcastConfigResponse(
+            const RadioResponseInfo& info,
+            const std::vector<GsmBroadcastSmsConfigInfo>& configs) override;
+
+    virtual ndk::ScopedAStatus getSmscAddressResponse(const RadioResponseInfo& info,
+                                                      const std::string& smsc) override;
+
+    virtual ndk::ScopedAStatus reportSmsMemoryStatusResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& info,
+                                                             const SendSmsResult& sms) override;
+
+    virtual ndk::ScopedAStatus sendCdmaSmsResponse(const RadioResponseInfo& info,
+                                                   const SendSmsResult& sms) override;
+
+    virtual ndk::ScopedAStatus sendImsSmsResponse(const RadioResponseInfo& info,
+                                                  const SendSmsResult& sms) override;
+
+    virtual ndk::ScopedAStatus sendSmsExpectMoreResponse(const RadioResponseInfo& info,
+                                                         const SendSmsResult& sms) override;
+
+    virtual ndk::ScopedAStatus sendSmsResponse(const RadioResponseInfo& info,
+                                               const SendSmsResult& sms) override;
+
+    virtual ndk::ScopedAStatus sendUssdResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCdmaBroadcastActivationResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCdmaBroadcastConfigResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setGsmBroadcastActivationResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setGsmBroadcastConfigResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setSmscAddressResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus writeSmsToRuimResponse(const RadioResponseInfo& info,
+                                                      int32_t index) override;
+
+    virtual ndk::ScopedAStatus writeSmsToSimResponse(const RadioResponseInfo& info,
+                                                     int32_t index) override;
+};
+
+/* Callback class for radio messaging indication */
+class RadioMessagingIndication : public BnRadioMessagingIndication {
+  protected:
+    RadioMessagingTest& parent_messaging;
+
+  public:
+    RadioMessagingIndication(RadioMessagingTest& parent_messaging);
+    virtual ~RadioMessagingIndication() = default;
+
+    virtual ndk::ScopedAStatus cdmaNewSms(RadioIndicationType type,
+                                          const CdmaSmsMessage& msg) override;
+
+    virtual ndk::ScopedAStatus cdmaRuimSmsStorageFull(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus newBroadcastSms(RadioIndicationType type,
+                                               const std::vector<uint8_t>& data) override;
+
+    virtual ndk::ScopedAStatus newSms(RadioIndicationType type,
+                                      const std::vector<uint8_t>& pdu) override;
+
+    virtual ndk::ScopedAStatus newSmsOnSim(RadioIndicationType type, int32_t recordNumber) override;
+
+    virtual ndk::ScopedAStatus newSmsStatusReport(RadioIndicationType type,
+                                                  const std::vector<uint8_t>& pdu) override;
+
+    virtual ndk::ScopedAStatus onUssd(RadioIndicationType type, UssdModeType modeType,
+                                      const std::string& msg) override;
+
+    virtual ndk::ScopedAStatus simSmsStorageFull(RadioIndicationType type) override;
+};
+
+// The main test class for Radio AIDL Messaging.
+class RadioMessagingTest : public ::testing::TestWithParam<std::string>,
+                           public RadioResponseWaiter {
+  public:
+    virtual void SetUp() override;
+
+    /* radio messaging service handle */
+    std::shared_ptr<IRadioMessaging> radio_messaging;
+    /* radio messaging response handle */
+    std::shared_ptr<RadioMessagingResponse> radioRsp_messaging;
+    /* radio messaging indication handle */
+    std::shared_ptr<RadioMessagingIndication> radioInd_messaging;
+};
diff --git a/radio/aidl/vts/radio_modem_indication.cpp b/radio/aidl/vts/radio_modem_indication.cpp
new file mode 100644
index 0000000..17f37a8
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_indication.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_modem_utils.h"
+
+RadioModemIndication::RadioModemIndication(RadioModemTest& parent) : parent_modem(parent) {}
+
+ndk::ScopedAStatus RadioModemIndication::hardwareConfigChanged(
+        RadioIndicationType /*type*/, const std::vector<HardwareConfig>& /*configs*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::modemReset(RadioIndicationType /*type*/,
+                                                    const std::string& /*reason*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::radioCapabilityIndication(RadioIndicationType /*type*/,
+                                                                   const RadioCapability& /*rc*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::radioStateChanged(RadioIndicationType /*type*/,
+                                                           RadioState /*radioState*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::rilConnected(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_modem_response.cpp b/radio/aidl/vts/radio_modem_response.cpp
new file mode 100644
index 0000000..7ac590f
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_response.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_modem_utils.h"
+
+RadioModemResponse::RadioModemResponse(RadioResponseWaiter& parent) : parent_modem(parent) {}
+
+ndk::ScopedAStatus RadioModemResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::enableModemResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getBasebandVersionResponse(const RadioResponseInfo& /*info*/,
+                                                                  const std::string& /*version*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getDeviceIdentityResponse(const RadioResponseInfo& /*info*/,
+                                                                 const std::string& /*imei*/,
+                                                                 const std::string& /*imeisv*/,
+                                                                 const std::string& /*esn*/,
+                                                                 const std::string& /*meid*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getHardwareConfigResponse(
+        const RadioResponseInfo& /*info*/, const std::vector<HardwareConfig>& /*config*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getModemActivityInfoResponse(
+        const RadioResponseInfo& /*info*/, const ActivityStatsInfo& /*activityInfo*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getModemStackStatusResponse(
+        const RadioResponseInfo& /*info*/, const bool /*enabled*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getRadioCapabilityResponse(const RadioResponseInfo& /*info*/,
+                                                                  const RadioCapability& /*rc*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvReadItemResponse(const RadioResponseInfo& /*info*/,
+                                                          const std::string& /*result*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvResetConfigResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvWriteCdmaPrlResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvWriteItemResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::requestShutdownResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::sendDeviceStateResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::setRadioCapabilityResponse(const RadioResponseInfo& /*info*/,
+                                                                  const RadioCapability& /*rc*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::setRadioPowerResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_modem_test.cpp b/radio/aidl/vts/radio_modem_test.cpp
new file mode 100644
index 0000000..406927f
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_test.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_modem_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioModemTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_modem = IRadioModem::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_modem.get());
+
+    radioRsp_modem = ndk::SharedRefBase::make<RadioModemResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_modem.get());
+
+    count_ = 0;
+
+    radioInd_modem = ndk::SharedRefBase::make<RadioModemIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_modem.get());
+
+    radio_modem->setResponseFunctions(radioRsp_modem, radioInd_modem);
+
+    // Assert IRadioConfig exists before testing
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
+            aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
+                    ndk::SpAIBinder(AServiceManager_waitForService(
+                            "android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radioConfig.get());
+}
+
+/*
+ * Test IRadioModem.setRadioPower() for the response returned.
+ */
+TEST_P(RadioModemTest, setRadioPower_emergencyCall_cancelled) {
+    // Set radio power to off.
+    serial = GetRandomSerialNumber();
+    radio_modem->setRadioPower(serial, false, false, false);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+
+    // Set radio power to on with forEmergencyCall being true. This should put modem to only scan
+    // emergency call bands.
+    serial = GetRandomSerialNumber();
+    radio_modem->setRadioPower(serial, true, true, true);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+
+    // Set radio power to on with forEmergencyCall being false. This should put modem in regular
+    // operation modem.
+    serial = GetRandomSerialNumber();
+    radio_modem->setRadioPower(serial, true, false, false);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+}
diff --git a/radio/aidl/vts/radio_modem_utils.h b/radio/aidl/vts/radio_modem_utils.h
new file mode 100644
index 0000000..cd9a30d
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_utils.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/modem/BnRadioModemIndication.h>
+#include <aidl/android/hardware/radio/modem/BnRadioModemResponse.h>
+#include <aidl/android/hardware/radio/modem/IRadioModem.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::config;
+using namespace aidl::android::hardware::radio::modem;
+
+class RadioModemTest;
+
+/* Callback class for radio modem response */
+class RadioModemResponse : public BnRadioModemResponse {
+  protected:
+    RadioResponseWaiter& parent_modem;
+
+  public:
+    RadioModemResponse(RadioResponseWaiter& parent_modem);
+    virtual ~RadioModemResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    bool isModemEnabled;
+    bool enableModemResponseToggle;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus enableModemResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getBasebandVersionResponse(const RadioResponseInfo& info,
+                                                          const std::string& version) override;
+
+    virtual ndk::ScopedAStatus getDeviceIdentityResponse(const RadioResponseInfo& info,
+                                                         const std::string& imei,
+                                                         const std::string& imeisv,
+                                                         const std::string& esn,
+                                                         const std::string& meid) override;
+
+    virtual ndk::ScopedAStatus getHardwareConfigResponse(
+            const RadioResponseInfo& info, const std::vector<HardwareConfig>& config) override;
+
+    virtual ndk::ScopedAStatus getModemActivityInfoResponse(
+            const RadioResponseInfo& info, const ActivityStatsInfo& activityInfo) override;
+
+    virtual ndk::ScopedAStatus getModemStackStatusResponse(const RadioResponseInfo& info,
+                                                           const bool enabled) override;
+
+    virtual ndk::ScopedAStatus getRadioCapabilityResponse(const RadioResponseInfo& info,
+                                                          const RadioCapability& rc) override;
+
+    virtual ndk::ScopedAStatus nvReadItemResponse(const RadioResponseInfo& info,
+                                                  const std::string& result) override;
+
+    virtual ndk::ScopedAStatus nvResetConfigResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus nvWriteCdmaPrlResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus nvWriteItemResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus requestShutdownResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendDeviceStateResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setRadioCapabilityResponse(const RadioResponseInfo& info,
+                                                          const RadioCapability& rc) override;
+
+    virtual ndk::ScopedAStatus setRadioPowerResponse(const RadioResponseInfo& info) override;
+};
+
+/* Callback class for radio modem indication */
+class RadioModemIndication : public BnRadioModemIndication {
+  protected:
+    RadioModemTest& parent_modem;
+
+  public:
+    RadioModemIndication(RadioModemTest& parent_modem);
+    virtual ~RadioModemIndication() = default;
+
+    virtual ndk::ScopedAStatus hardwareConfigChanged(
+            RadioIndicationType type, const std::vector<HardwareConfig>& configs) override;
+
+    virtual ndk::ScopedAStatus modemReset(RadioIndicationType type,
+                                          const std::string& reason) override;
+
+    virtual ndk::ScopedAStatus radioCapabilityIndication(RadioIndicationType type,
+                                                         const RadioCapability& rc) override;
+
+    virtual ndk::ScopedAStatus radioStateChanged(RadioIndicationType type,
+                                                 RadioState radioState) override;
+
+    virtual ndk::ScopedAStatus rilConnected(RadioIndicationType type) override;
+};
+
+// The main test class for Radio AIDL Modem.
+class RadioModemTest : public ::testing::TestWithParam<std::string>, public RadioResponseWaiter {
+  public:
+    virtual void SetUp() override;
+
+    /* radio modem service handle */
+    std::shared_ptr<IRadioModem> radio_modem;
+    /* radio modem response handle */
+    std::shared_ptr<RadioModemResponse> radioRsp_modem;
+    /* radio modem indication handle */
+    std::shared_ptr<RadioModemIndication> radioInd_modem;
+};
diff --git a/radio/aidl/vts/radio_network_indication.cpp b/radio/aidl/vts/radio_network_indication.cpp
new file mode 100644
index 0000000..7bed759
--- /dev/null
+++ b/radio/aidl/vts/radio_network_indication.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_network_utils.h"
+
+RadioNetworkIndication::RadioNetworkIndication(RadioNetworkTest& parent) : parent_network(parent) {}
+
+ndk::ScopedAStatus RadioNetworkIndication::barringInfoChanged(
+        RadioIndicationType /*type*/, const CellIdentity& /*cellIdentity*/,
+        const std::vector<BarringInfo>& /*barringInfos*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::cdmaPrlChanged(RadioIndicationType /*type*/,
+                                                          int32_t /*version*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::cellInfoList(RadioIndicationType /*type*/,
+                                                        const std::vector<CellInfo>& /*records*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::currentLinkCapacityEstimate(
+        RadioIndicationType /*type*/, const LinkCapacityEstimate& /*lce*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::currentPhysicalChannelConfigs(
+        RadioIndicationType /*type*/, const std::vector<PhysicalChannelConfig>& /*configs*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::currentSignalStrength(
+        RadioIndicationType /*type*/, const SignalStrength& /*signalStrength*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::imsNetworkStateChanged(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::networkScanResult(RadioIndicationType /*type*/,
+                                                             const NetworkScanResult& /*result*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::networkStateChanged(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::nitzTimeReceived(RadioIndicationType /*type*/,
+                                                            const std::string& /*nitzTime*/,
+                                                            int64_t /*receivedTime*/,
+                                                            int64_t /*age*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::registrationFailed(RadioIndicationType /*type*/,
+                                                              const CellIdentity& /*cellIdentity*/,
+                                                              const std::string& /*chosenPlmn*/,
+                                                              Domain /*domain*/,
+                                                              int32_t /*causeCode*/,
+                                                              int32_t /*additionalCauseCode*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::restrictedStateChanged(RadioIndicationType /*type*/,
+                                                                  PhoneRestrictedState /*state*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::suppSvcNotify(RadioIndicationType /*type*/,
+                                                         const SuppSvcNotification& /*suppSvc*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::voiceRadioTechChanged(RadioIndicationType /*type*/,
+                                                                 RadioTechnology /*rat*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_network_response.cpp b/radio/aidl/vts/radio_network_response.cpp
new file mode 100644
index 0000000..b242341
--- /dev/null
+++ b/radio/aidl/vts/radio_network_response.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_network_utils.h"
+
+RadioNetworkResponse::RadioNetworkResponse(RadioResponseWaiter& parent) : parent_network(parent) {}
+
+ndk::ScopedAStatus RadioNetworkResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getAllowedNetworkTypesBitmapResponse(
+        const RadioResponseInfo& info, const RadioAccessFamily networkTypeBitmap) {
+    rspInfo = info;
+    networkTypeBitmapResponse = networkTypeBitmap;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getAvailableBandModesResponse(
+        const RadioResponseInfo& /*info*/, const std::vector<RadioBandMode>& /*bandModes*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getAvailableNetworksResponse(
+        const RadioResponseInfo& info, const std::vector<OperatorInfo>& operatorInfos) {
+    rspInfo = info;
+    networkInfos = operatorInfos;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getBarringInfoResponse(
+        const RadioResponseInfo& /*info*/, const CellIdentity& /*cellIdentity*/,
+        const std::vector<BarringInfo>& /*barringInfos*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getCdmaRoamingPreferenceResponse(
+        const RadioResponseInfo& /*info*/, CdmaRoamingType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getCellInfoListResponse(
+        const RadioResponseInfo& /*info*/, const std::vector<CellInfo>& /*cellInfo*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getDataRegistrationStateResponse(
+        const RadioResponseInfo& info, const RegStateResult& /*regResponse*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getImsRegistrationStateResponse(
+        const RadioResponseInfo& /*info*/, bool /*isRegistered*/,
+        RadioTechnologyFamily /*ratFamily*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getNetworkSelectionModeResponse(
+        const RadioResponseInfo& /*info*/, bool /*manual*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getOperatorResponse(const RadioResponseInfo& /*info*/,
+                                                             const std::string& /*longName*/,
+                                                             const std::string& /*shortName*/,
+                                                             const std::string& /*numeric*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getSignalStrengthResponse(
+        const RadioResponseInfo& /*info*/, const SignalStrength& /*sig_strength*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getSystemSelectionChannelsResponse(
+        const RadioResponseInfo& info, const std::vector<RadioAccessSpecifier>& /*specifier*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getUsageSettingResponse(const RadioResponseInfo& info,
+                                                                 const UsageSetting usageSetting) {
+    rspInfo = info;
+    this->usageSetting = usageSetting;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getVoiceRadioTechnologyResponse(
+        const RadioResponseInfo& /*info*/, RadioTechnology /*rat*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getVoiceRegistrationStateResponse(
+        const RadioResponseInfo& info, const RegStateResult& regResponse) {
+    rspInfo = info;
+    regStateResp.regState = regResponse.regState;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::isNrDualConnectivityEnabledResponse(
+        const RadioResponseInfo& info, bool isEnabled) {
+    rspInfo = info;
+    isNrDualConnectivityEnabled = isEnabled;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setAllowedNetworkTypesBitmapResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setBandModeResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setBarringPasswordResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setCdmaRoamingPreferenceResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setCellInfoListRateResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setIndicationFilterResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setLinkCapacityReportingCriteriaResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setLocationUpdatesResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setNetworkSelectionModeAutomaticResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setNetworkSelectionModeManualResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setNrDualConnectivityStateResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setSignalStrengthReportingCriteriaResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setSuppServiceNotificationsResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setSystemSelectionChannelsResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setUsageSettingResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::startNetworkScanResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::stopNetworkScanResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::supplyNetworkDepersonalizationResponse(
+        const RadioResponseInfo& /*info*/, int32_t /*remainingRetries*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
new file mode 100644
index 0000000..1cdbb6d
--- /dev/null
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_network_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioNetworkTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_network = IRadioNetwork::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_network.get());
+
+    radioRsp_network = ndk::SharedRefBase::make<RadioNetworkResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_network.get());
+
+    count_ = 0;
+
+    radioInd_network = ndk::SharedRefBase::make<RadioNetworkIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_network.get());
+
+    radio_network->setResponseFunctions(radioRsp_network, radioInd_network);
+
+    // Assert IRadioConfig exists before testing
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
+            aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
+                    ndk::SpAIBinder(AServiceManager_waitForService(
+                            "android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radioConfig.get());
+}
+
+/*
+ * Test IRadioNetwork.setAllowedNetworkTypesBitmap for the response returned.
+ */
+TEST_P(RadioNetworkTest, setAllowedNetworkTypesBitmap) {
+    serial = GetRandomSerialNumber();
+    RadioAccessFamily allowedNetworkTypesBitmap = RadioAccessFamily::LTE;
+
+    radio_network->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_network->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::OPERATION_NOT_ALLOWED,
+             RadioError::MODE_NOT_SUPPORTED, RadioError::INTERNAL_ERR, RadioError::MODEM_ERR,
+             RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
+             RadioError::NO_RESOURCES}));
+}
+
+/*
+ * Test IRadioNetwork.getAllowedNetworkTypesBitmap for the response returned.
+ */
+TEST_P(RadioNetworkTest, getAllowedNetworkTypesBitmap) {
+    serial = GetRandomSerialNumber();
+    RadioAccessFamily allowedNetworkTypesBitmap = RadioAccessFamily::LTE;
+
+    radio_network->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+        sleep(3);  // wait for modem
+        serial = GetRandomSerialNumber();
+        radio_network->getAllowedNetworkTypesBitmap(serial);
+
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR,
+                 RadioError::OPERATION_NOT_ALLOWED, RadioError::MODE_NOT_SUPPORTED,
+                 RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR,
+                 RadioError::REQUEST_NOT_SUPPORTED, RadioError::NO_RESOURCES}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.setNrDualConnectivityState() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setNrDualConnectivityState) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res =
+            radio_network->setNrDualConnectivityState(serial, NrDualConnectivityState::DISABLE);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR,
+                 RadioError::INVALID_STATE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.isNrDualConnectivityEnabled() for the response returned.
+ */
+TEST_P(RadioNetworkTest, isNrDualConnectivityEnabled) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_network->isNrDualConnectivityEnabled(serial);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR, RadioError::NONE}));
+    }
+}
+
+void RadioNetworkTest::invokeAndExpectResponse(
+        std::function<ndk::ScopedAStatus(int32_t serial)> request,
+        std::vector<RadioError> errors_to_check) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = request(serial);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, errors_to_check));
+}
+
+/*
+ * Test IRadioNetwork.getUsageSetting()
+ *
+ * Verify that the usage setting can be retrieved.
+ */
+TEST_P(RadioNetworkTest, getUsageSetting) {
+    invokeAndExpectResponse([&](int serial) { return radio_network->getUsageSetting(serial); },
+                            {RadioError::RADIO_NOT_AVAILABLE, RadioError::INVALID_STATE,
+                             RadioError::SIM_ABSENT, RadioError::INTERNAL_ERR, RadioError::NONE});
+
+    ASSERT_TRUE(radioRsp_network->usageSetting == UsageSetting::VOICE_CENTRIC ||
+                radioRsp_network->usageSetting == UsageSetting::DATA_CENTRIC);
+}
+
+void RadioNetworkTest::testSetUsageSetting_InvalidValues(std::vector<RadioError> errors) {
+    invokeAndExpectResponse(
+            [&](int serial) {
+                return radio_network->setUsageSetting(serial,
+                                                      UsageSetting(0) /*below valid range*/);
+            },
+            errors);
+    invokeAndExpectResponse(
+            [&](int serial) {
+                return radio_network->setUsageSetting(serial, UsageSetting(-1) /*negative*/);
+            },
+            errors);
+    invokeAndExpectResponse(
+            [&](int serial) {
+                return radio_network->setUsageSetting(serial,
+                                                      UsageSetting(3) /*above valid range*/);
+            },
+            errors);
+}
+
+/*
+ * Test IRadioNetwork.setUsageSetting() and IRadioNetwork.getUsageSetting()
+ *
+ * Verify the following:
+ * -That the usage setting can be retrieved.
+ * -That the usage setting can be successfully set to allowed values.
+ * -That the usage setting cannot be set to invalid values.
+ */
+TEST_P(RadioNetworkTest, setUsageSetting) {
+    invokeAndExpectResponse([&](int serial) { return radio_network->getUsageSetting(serial); },
+                            {RadioError::RADIO_NOT_AVAILABLE, RadioError::INVALID_STATE,
+                             RadioError::SIM_ABSENT, RadioError::INTERNAL_ERR, RadioError::NONE});
+
+    if (radioRsp_network->rspInfo.error != RadioError::NONE) {
+        // Test only for invalid values, with the only allowable response being the same error
+        // that was previously provided, or an error indicating invalid arguments.
+        testSetUsageSetting_InvalidValues(
+                {radioRsp_network->rspInfo.error, RadioError::INVALID_ARGUMENTS});
+        // It is unsafe to proceed with setting valid values without knowing the starting value, but
+        // we expect errors anyway, so not necessary.
+        return;
+    } else {
+        // Because querying succeeded, the device is in a valid state to test for invalid values
+        // and the only thing that can change is that we expect to have an EINVAL return each time.
+        testSetUsageSetting_InvalidValues({RadioError::INVALID_ARGUMENTS});
+    }
+
+    // Store the original setting value to reset later.
+    const UsageSetting originalSetting = radioRsp_network->usageSetting;
+
+    // Choose the "other" value that is not the current value for test.
+    const UsageSetting testSetting = radioRsp_network->usageSetting == UsageSetting::VOICE_CENTRIC
+                                             ? UsageSetting::DATA_CENTRIC
+                                             : UsageSetting::VOICE_CENTRIC;
+
+    // Set an alternative setting; it may either succeed or be disallowed as out of range for
+    // the current device (if the device only supports its current mode).
+    invokeAndExpectResponse(
+            [&](int serial) { return radio_network->setUsageSetting(serial, testSetting); },
+            {RadioError::INVALID_ARGUMENTS, RadioError::NONE});
+
+    // If there was no error, then we expect the test setting to be set, or if there is an error
+    // we expect the original setting to be maintained.
+    const UsageSetting expectedSetting =
+            radioRsp_network->rspInfo.error == RadioError::NONE ? testSetting : originalSetting;
+    invokeAndExpectResponse([&](int serial) { return radio_network->getUsageSetting(serial); },
+                            {RadioError::NONE});
+
+    const UsageSetting updatedSetting = radioRsp_network->usageSetting;
+
+    // Re-set the original setting, which must always succeed.
+    invokeAndExpectResponse(
+            [&](int serial) { return radio_network->setUsageSetting(serial, originalSetting); },
+            {RadioError::NONE});
+
+    // Check that indeed the updated setting was set. We do this after resetting to original
+    // conditions to avoid early-exiting the test and leaving the device in a modified state.
+    ASSERT_TRUE(expectedSetting == updatedSetting);
+    // Check that indeed the original setting was reset.
+    ASSERT_TRUE(originalSetting == radioRsp_network->usageSetting);
+}
diff --git a/radio/aidl/vts/radio_network_utils.h b/radio/aidl/vts/radio_network_utils.h
new file mode 100644
index 0000000..caa1ecc
--- /dev/null
+++ b/radio/aidl/vts/radio_network_utils.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/network/BnRadioNetworkIndication.h>
+#include <aidl/android/hardware/radio/network/BnRadioNetworkResponse.h>
+#include <aidl/android/hardware/radio/network/IRadioNetwork.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::network;
+
+class RadioNetworkTest;
+
+/* Callback class for radio network response */
+class RadioNetworkResponse : public BnRadioNetworkResponse {
+  protected:
+    RadioResponseWaiter& parent_network;
+
+  public:
+    RadioNetworkResponse(RadioResponseWaiter& parent_network);
+    virtual ~RadioNetworkResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    std::vector<RadioBandMode> radioBandModes;
+    std::vector<OperatorInfo> networkInfos;
+    bool isNrDualConnectivityEnabled;
+    RadioAccessFamily networkTypeBitmapResponse;
+    RegStateResult regStateResp;
+    CellIdentity barringCellIdentity;
+    std::vector<BarringInfo> barringInfos;
+    UsageSetting usageSetting;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus getAllowedNetworkTypesBitmapResponse(
+            const RadioResponseInfo& info, const RadioAccessFamily networkTypeBitmap) override;
+
+    virtual ndk::ScopedAStatus getAvailableBandModesResponse(
+            const RadioResponseInfo& info, const std::vector<RadioBandMode>& bandModes) override;
+
+    virtual ndk::ScopedAStatus getAvailableNetworksResponse(
+            const RadioResponseInfo& info, const std::vector<OperatorInfo>& networkInfos) override;
+
+    virtual ndk::ScopedAStatus getBarringInfoResponse(
+            const RadioResponseInfo& info, const CellIdentity& cellIdentity,
+            const std::vector<BarringInfo>& barringInfos) override;
+
+    virtual ndk::ScopedAStatus getCdmaRoamingPreferenceResponse(const RadioResponseInfo& info,
+                                                                CdmaRoamingType type) override;
+
+    virtual ndk::ScopedAStatus getCellInfoListResponse(
+            const RadioResponseInfo& info, const std::vector<CellInfo>& cellInfo) override;
+
+    virtual ndk::ScopedAStatus getDataRegistrationStateResponse(
+            const RadioResponseInfo& info, const RegStateResult& dataRegResponse) override;
+
+    virtual ndk::ScopedAStatus getImsRegistrationStateResponse(
+            const RadioResponseInfo& info, bool isRegistered,
+            RadioTechnologyFamily ratFamily) override;
+
+    virtual ndk::ScopedAStatus getNetworkSelectionModeResponse(const RadioResponseInfo& info,
+                                                               bool manual) override;
+
+    virtual ndk::ScopedAStatus getOperatorResponse(const RadioResponseInfo& info,
+                                                   const std::string& longName,
+                                                   const std::string& shortName,
+                                                   const std::string& numeric) override;
+
+    virtual ndk::ScopedAStatus getSignalStrengthResponse(
+            const RadioResponseInfo& info, const SignalStrength& sigStrength) override;
+
+    virtual ndk::ScopedAStatus getSystemSelectionChannelsResponse(
+            const RadioResponseInfo& info,
+            const std::vector<RadioAccessSpecifier>& specifier) override;
+
+    virtual ndk::ScopedAStatus getUsageSettingResponse(const RadioResponseInfo& info,
+                                                       UsageSetting usageSetting) override;
+
+    virtual ndk::ScopedAStatus getVoiceRadioTechnologyResponse(const RadioResponseInfo& info,
+                                                               RadioTechnology rat) override;
+
+    virtual ndk::ScopedAStatus getVoiceRegistrationStateResponse(
+            const RadioResponseInfo& info, const RegStateResult& voiceRegResponse) override;
+
+    virtual ndk::ScopedAStatus isNrDualConnectivityEnabledResponse(const RadioResponseInfo& info,
+                                                                   bool isEnabled) override;
+
+    virtual ndk::ScopedAStatus setAllowedNetworkTypesBitmapResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setBandModeResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setBarringPasswordResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCdmaRoamingPreferenceResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCellInfoListRateResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setIndicationFilterResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setLinkCapacityReportingCriteriaResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setLocationUpdatesResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setNetworkSelectionModeAutomaticResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setNetworkSelectionModeManualResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setNrDualConnectivityStateResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setSignalStrengthReportingCriteriaResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setSuppServiceNotificationsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setSystemSelectionChannelsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setUsageSettingResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus startNetworkScanResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus stopNetworkScanResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus supplyNetworkDepersonalizationResponse(
+            const RadioResponseInfo& info, int32_t remainingRetries) override;
+};
+
+/* Callback class for radio network indication */
+class RadioNetworkIndication : public BnRadioNetworkIndication {
+  protected:
+    RadioNetworkTest& parent_network;
+
+  public:
+    RadioNetworkIndication(RadioNetworkTest& parent_network);
+    virtual ~RadioNetworkIndication() = default;
+
+    virtual ndk::ScopedAStatus barringInfoChanged(
+            RadioIndicationType type, const CellIdentity& cellIdentity,
+            const std::vector<BarringInfo>& barringInfos) override;
+
+    virtual ndk::ScopedAStatus cdmaPrlChanged(RadioIndicationType type, int32_t version) override;
+
+    virtual ndk::ScopedAStatus cellInfoList(RadioIndicationType type,
+                                            const std::vector<CellInfo>& records) override;
+
+    virtual ndk::ScopedAStatus currentLinkCapacityEstimate(
+            RadioIndicationType type, const LinkCapacityEstimate& lce) override;
+
+    virtual ndk::ScopedAStatus currentPhysicalChannelConfigs(
+            RadioIndicationType type, const std::vector<PhysicalChannelConfig>& configs) override;
+
+    virtual ndk::ScopedAStatus currentSignalStrength(RadioIndicationType type,
+                                                     const SignalStrength& signalStrength) override;
+
+    virtual ndk::ScopedAStatus imsNetworkStateChanged(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus networkScanResult(RadioIndicationType type,
+                                                 const NetworkScanResult& result) override;
+
+    virtual ndk::ScopedAStatus networkStateChanged(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus nitzTimeReceived(RadioIndicationType type,
+                                                const std::string& nitzTime, int64_t receivedTimeMs,
+                                                int64_t ageMs) override;
+
+    virtual ndk::ScopedAStatus registrationFailed(RadioIndicationType type,
+                                                  const CellIdentity& cellIdentity,
+                                                  const std::string& chosenPlmn, Domain domain,
+                                                  int32_t causeCode,
+                                                  int32_t additionalCauseCode) override;
+
+    virtual ndk::ScopedAStatus restrictedStateChanged(RadioIndicationType type,
+                                                      PhoneRestrictedState state) override;
+
+    virtual ndk::ScopedAStatus suppSvcNotify(RadioIndicationType type,
+                                             const SuppSvcNotification& suppSvc) override;
+
+    virtual ndk::ScopedAStatus voiceRadioTechChanged(RadioIndicationType type,
+                                                     RadioTechnology rat) override;
+};
+
+// The main test class for Radio AIDL Network.
+class RadioNetworkTest : public ::testing::TestWithParam<std::string>, public RadioResponseWaiter {
+  public:
+    virtual void SetUp() override;
+
+    /* radio network service handle */
+    std::shared_ptr<IRadioNetwork> radio_network;
+    /* radio network response handle */
+    std::shared_ptr<RadioNetworkResponse> radioRsp_network;
+    /* radio network indication handle */
+    std::shared_ptr<RadioNetworkIndication> radioInd_network;
+
+    void invokeAndExpectResponse(std::function<ndk::ScopedAStatus(int32_t serial)> request,
+                                 std::vector<RadioError> errors_to_check);
+
+    // Helper function to reduce copy+paste
+    void testSetUsageSetting_InvalidValues(std::vector<RadioError> errors);
+};
diff --git a/radio/aidl/vts/radio_sim_indication.cpp b/radio/aidl/vts/radio_sim_indication.cpp
new file mode 100644
index 0000000..0385845
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_indication.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_sim_utils.h"
+
+RadioSimIndication::RadioSimIndication(RadioSimTest& parent) : parent_sim(parent) {}
+
+ndk::ScopedAStatus RadioSimIndication::carrierInfoForImsiEncryption(RadioIndicationType /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::cdmaSubscriptionSourceChanged(
+        RadioIndicationType /*type*/, CdmaSubscriptionSource /*cdmaSource*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simPhonebookChanged(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simPhonebookRecordsReceived(
+        RadioIndicationType /*type*/, PbReceivedStatus /*status*/,
+        const std::vector<PhonebookRecordInfo>& /*records*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simRefresh(RadioIndicationType /*type*/,
+                                                  const SimRefreshResult& /*refreshResult*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simStatusChanged(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::stkEventNotify(RadioIndicationType /*type*/,
+                                                      const std::string& /*cmd*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::stkProactiveCommand(RadioIndicationType /*type*/,
+                                                           const std::string& /*cmd*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::stkSessionEnd(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::subscriptionStatusChanged(RadioIndicationType /*type*/,
+                                                                 bool /*activate*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::uiccApplicationsEnablementChanged(
+        RadioIndicationType /*type*/, bool /*enabled*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_sim_response.cpp b/radio/aidl/vts/radio_sim_response.cpp
new file mode 100644
index 0000000..2c796fa
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_response.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_sim_utils.h"
+
+RadioSimResponse::RadioSimResponse(RadioResponseWaiter& parent) : parent_sim(parent) {}
+
+ndk::ScopedAStatus RadioSimResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::areUiccApplicationsEnabledResponse(
+        const RadioResponseInfo& /*info*/, bool /*enabled*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::changeIccPin2ForAppResponse(const RadioResponseInfo& /*info*/,
+                                                                 int32_t /*remainingRetries*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::changeIccPinForAppResponse(const RadioResponseInfo& /*info*/,
+                                                                int32_t /*remainingRetries*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::enableUiccApplicationsResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getAllowedCarriersResponse(
+        const RadioResponseInfo& /*info*/, const CarrierRestrictions& /*carriers*/,
+        SimLockMultiSimPolicy /*multiSimPolicy*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getCdmaSubscriptionResponse(
+        const RadioResponseInfo& /*info*/, const std::string& /*mdn*/, const std::string& /*hSid*/,
+        const std::string& /*hNid*/, const std::string& /*min*/, const std::string& /*prl*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getCdmaSubscriptionSourceResponse(
+        const RadioResponseInfo& /*info*/, CdmaSubscriptionSource /*source*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getFacilityLockForAppResponse(
+        const RadioResponseInfo& /*info*/, int32_t /*response*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getIccCardStatusResponse(const RadioResponseInfo& info,
+                                                              const CardStatus& card_status) {
+    rspInfo = info;
+    cardStatus = card_status;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getImsiForAppResponse(const RadioResponseInfo& /*info*/,
+                                                           const std::string& /*imsi*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getSimPhonebookCapacityResponse(
+        const RadioResponseInfo& info, const PhonebookCapacity& pbCapacity) {
+    rspInfo = info;
+    capacity = pbCapacity;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getSimPhonebookRecordsResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccCloseLogicalChannelResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccIoForAppResponse(const RadioResponseInfo& /*info*/,
+                                                         const IccIoResult& /*iccIo*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccOpenLogicalChannelResponse(
+        const RadioResponseInfo& /*info*/, int32_t /*channelId*/,
+        const std::vector<uint8_t>& /*selectResponse*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccTransmitApduBasicChannelResponse(
+        const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccTransmitApduLogicalChannelResponse(
+        const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::reportStkServiceIsRunningResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::requestIccSimAuthenticationResponse(
+        const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::sendEnvelopeResponse(const RadioResponseInfo& /*info*/,
+                                                          const std::string& /*commandResponse*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::sendEnvelopeWithStatusResponse(
+        const RadioResponseInfo& /*info*/, const IccIoResult& /*iccIo*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::sendTerminalResponseToSimResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setAllowedCarriersResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setCarrierInfoForImsiEncryptionResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setCdmaSubscriptionSourceResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setFacilityLockForAppResponse(
+        const RadioResponseInfo& /*info*/, int32_t /*retry*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setSimCardPowerResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setUiccSubscriptionResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPin2ForAppResponse(const RadioResponseInfo& /*info*/,
+                                                                 int32_t /*remainingRetries*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPinForAppResponse(const RadioResponseInfo& /*info*/,
+                                                                int32_t /*remainingRetries*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPuk2ForAppResponse(const RadioResponseInfo& /*info*/,
+                                                                 int32_t /*remainingRetries*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPukForAppResponse(const RadioResponseInfo& /*info*/,
+                                                                int32_t /*remainingRetries*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplySimDepersonalizationResponse(
+        const RadioResponseInfo& /*info*/, PersoSubstate /*persoType*/,
+        int32_t /*remainingRetries*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::updateSimPhonebookRecordsResponse(
+        const RadioResponseInfo& info, int32_t recordIndex) {
+    rspInfo = info;
+    updatedRecordIndex = recordIndex;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_sim_test.cpp b/radio/aidl/vts/radio_sim_test.cpp
new file mode 100644
index 0000000..c70219f
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_test.cpp
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_sim_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioSimTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_sim = IRadioSim::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_sim.get());
+
+    radioRsp_sim = ndk::SharedRefBase::make<RadioSimResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_sim.get());
+
+    count_ = 0;
+
+    radioInd_sim = ndk::SharedRefBase::make<RadioSimIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_sim.get());
+
+    radio_sim->setResponseFunctions(radioRsp_sim, radioInd_sim);
+
+    // Assert IRadioConfig exists before testing
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
+            aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
+                    ndk::SpAIBinder(AServiceManager_waitForService(
+                            "android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radioConfig.get());
+}
+
+ndk::ScopedAStatus RadioSimTest::updateSimCardStatus() {
+    serial = GetRandomSerialNumber();
+    radio_sim->getIccCardStatus(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    return ndk::ScopedAStatus::ok();
+}
+
+/*
+ * Test IRadioSim.setSimCardPower() for the response returned.
+ */
+TEST_P(RadioSimTest, setSimCardPower) {
+    /* Test setSimCardPower power down */
+    serial = GetRandomSerialNumber();
+    radio_sim->setSimCardPower(serial, CardPowerState::POWER_DOWN);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                  RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ERR}));
+
+    // setSimCardPower does not return  until the request is handled, and should not trigger
+    // CardStatus::STATE_ABSENT when turning off power
+    if (radioRsp_sim->rspInfo.error == RadioError::NONE) {
+        /* Wait some time for setting sim power down and then verify it */
+        updateSimCardStatus();
+        // We cannot assert the consistency of CardState here due to b/203031664
+        // EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+        // applications should be an empty vector of AppStatus
+        EXPECT_EQ(0, cardStatus.applications.size());
+    }
+
+    // Give some time for modem to fully power down the SIM card
+    sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+
+    /* Test setSimCardPower power up */
+    serial = GetRandomSerialNumber();
+    radio_sim->setSimCardPower(serial, CardPowerState::POWER_UP);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                  RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ERR}));
+
+    // Give some time for modem to fully power up the SIM card
+    sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+
+    // setSimCardPower does not return  until the request is handled. Just verify that we still
+    // have CardStatus::STATE_PRESENT after turning the power back on
+    if (radioRsp_sim->rspInfo.error == RadioError::NONE) {
+        updateSimCardStatus();
+        EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+    }
+}
+
+/*
+ * Test IRadioSim.setCarrierInfoForImsiEncryption() for the response returned.
+ */
+TEST_P(RadioSimTest, setCarrierInfoForImsiEncryption) {
+    serial = GetRandomSerialNumber();
+    ImsiEncryptionInfo imsiInfo;
+    imsiInfo.mcc = "310";
+    imsiInfo.mnc = "004";
+    imsiInfo.carrierKey = (std::vector<uint8_t>){1, 2, 3, 4, 5, 6};
+    imsiInfo.keyIdentifier = "Test";
+    imsiInfo.expirationTime = 20180101;
+    imsiInfo.keyType = ImsiEncryptionInfo::PUBLIC_KEY_TYPE_EPDG;
+
+    radio_sim->setCarrierInfoForImsiEncryption(serial, imsiInfo);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadioSim.getSimPhonebookRecords() for the response returned.
+ */
+TEST_P(RadioSimTest, getSimPhonebookRecords) {
+    serial = GetRandomSerialNumber();
+    radio_sim->getSimPhonebookRecords(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(
+                CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::INVALID_SIM_STATE, RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS,
+                                  RadioError::REQUEST_NOT_SUPPORTED},
+                                 CHECK_GENERAL_ERROR));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+                                     CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadioSim.getSimPhonebookCapacity for the response returned.
+ */
+TEST_P(RadioSimTest, getSimPhonebookCapacity) {
+    serial = GetRandomSerialNumber();
+    radio_sim->getSimPhonebookCapacity(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(
+                CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::INVALID_SIM_STATE, RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS,
+                                  RadioError::REQUEST_NOT_SUPPORTED},
+                                 CHECK_GENERAL_ERROR));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+                                     CHECK_GENERAL_ERROR));
+
+        PhonebookCapacity pbCapacity = radioRsp_sim->capacity;
+        if (pbCapacity.maxAdnRecords > 0) {
+            EXPECT_TRUE(pbCapacity.maxNameLen > 0 && pbCapacity.maxNumberLen > 0);
+            EXPECT_TRUE(pbCapacity.usedAdnRecords <= pbCapacity.maxAdnRecords);
+        }
+
+        if (pbCapacity.maxEmailRecords > 0) {
+            EXPECT_TRUE(pbCapacity.maxEmailLen > 0);
+            EXPECT_TRUE(pbCapacity.usedEmailRecords <= pbCapacity.maxEmailRecords);
+        }
+
+        if (pbCapacity.maxAdditionalNumberRecords > 0) {
+            EXPECT_TRUE(pbCapacity.maxAdditionalNumberLen > 0);
+            EXPECT_TRUE(pbCapacity.usedAdditionalNumberRecords <=
+                        pbCapacity.maxAdditionalNumberRecords);
+        }
+    }
+}
+
+/*
+ * Test IRadioSim.updateSimPhonebookRecords() for the response returned.
+ */
+TEST_P(RadioSimTest, updateSimPhonebookRecords) {
+    serial = GetRandomSerialNumber();
+    radio_sim->getSimPhonebookCapacity(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(
+                CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::INVALID_SIM_STATE, RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS,
+                                  RadioError::REQUEST_NOT_SUPPORTED},
+                                 CHECK_GENERAL_ERROR));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+                                     CHECK_GENERAL_ERROR));
+        PhonebookCapacity pbCapacity = radioRsp_sim->capacity;
+
+        serial = GetRandomSerialNumber();
+        radio_sim->getSimPhonebookRecords(serial);
+
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+                                     CHECK_GENERAL_ERROR));
+
+        if (pbCapacity.maxAdnRecords > 0 && pbCapacity.usedAdnRecords < pbCapacity.maxAdnRecords) {
+            // Add a phonebook record
+            PhonebookRecordInfo recordInfo;
+            recordInfo.recordId = 0;
+            recordInfo.name = "ABC";
+            recordInfo.number = "1234567890";
+            serial = GetRandomSerialNumber();
+            radio_sim->updateSimPhonebookRecords(serial, recordInfo);
+
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+            EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+            EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+            int index = radioRsp_sim->updatedRecordIndex;
+            EXPECT_TRUE(index > 0);
+
+            // Deleted a phonebook record
+            recordInfo.recordId = index;
+            recordInfo.name = "";
+            recordInfo.number = "";
+            serial = GetRandomSerialNumber();
+            radio_sim->updateSimPhonebookRecords(serial, recordInfo);
+
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+            EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+            EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+        }
+    }
+}
diff --git a/radio/aidl/vts/radio_sim_utils.h b/radio/aidl/vts/radio_sim_utils.h
new file mode 100644
index 0000000..6cb6790
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_utils.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/sim/BnRadioSimIndication.h>
+#include <aidl/android/hardware/radio/sim/BnRadioSimResponse.h>
+#include <aidl/android/hardware/radio/sim/IRadioSim.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::sim;
+
+class RadioSimTest;
+
+/* Callback class for radio SIM response */
+class RadioSimResponse : public BnRadioSimResponse {
+  protected:
+    RadioResponseWaiter& parent_sim;
+
+  public:
+    RadioSimResponse(RadioResponseWaiter& parent_sim);
+    virtual ~RadioSimResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    CarrierRestrictions carrierRestrictionsResp;
+    SimLockMultiSimPolicy multiSimPolicyResp;
+    bool canToggleUiccApplicationsEnablement;
+    bool areUiccApplicationsEnabled;
+    PhonebookCapacity capacity;
+    int32_t updatedRecordIndex;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus areUiccApplicationsEnabledResponse(const RadioResponseInfo& info,
+                                                                  bool enabled) override;
+
+    virtual ndk::ScopedAStatus changeIccPin2ForAppResponse(const RadioResponseInfo& info,
+                                                           int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus changeIccPinForAppResponse(const RadioResponseInfo& info,
+                                                          int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus enableUiccApplicationsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getAllowedCarriersResponse(
+            const RadioResponseInfo& info, const CarrierRestrictions& carriers,
+            const SimLockMultiSimPolicy multiSimPolicy) override;
+
+    virtual ndk::ScopedAStatus getCdmaSubscriptionResponse(
+            const RadioResponseInfo& info, const std::string& mdn, const std::string& hSid,
+            const std::string& hNid, const std::string& min, const std::string& prl) override;
+
+    virtual ndk::ScopedAStatus getCdmaSubscriptionSourceResponse(
+            const RadioResponseInfo& info, CdmaSubscriptionSource source) override;
+
+    virtual ndk::ScopedAStatus getFacilityLockForAppResponse(const RadioResponseInfo& info,
+                                                             int32_t response) override;
+
+    virtual ndk::ScopedAStatus getIccCardStatusResponse(const RadioResponseInfo& info,
+                                                        const CardStatus& cardStatus) override;
+
+    virtual ndk::ScopedAStatus getImsiForAppResponse(const RadioResponseInfo& info,
+                                                     const std::string& imsi) override;
+
+    virtual ndk::ScopedAStatus getSimPhonebookCapacityResponse(
+            const RadioResponseInfo& info, const PhonebookCapacity& capacity) override;
+
+    virtual ndk::ScopedAStatus getSimPhonebookRecordsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus iccCloseLogicalChannelResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus iccIoForAppResponse(const RadioResponseInfo& info,
+                                                   const IccIoResult& iccIo) override;
+
+    virtual ndk::ScopedAStatus iccOpenLogicalChannelResponse(
+            const RadioResponseInfo& info, int32_t channelId,
+            const std::vector<uint8_t>& selectResponse) override;
+
+    virtual ndk::ScopedAStatus iccTransmitApduBasicChannelResponse(
+            const RadioResponseInfo& info, const IccIoResult& result) override;
+
+    virtual ndk::ScopedAStatus iccTransmitApduLogicalChannelResponse(
+            const RadioResponseInfo& info, const IccIoResult& result) override;
+
+    virtual ndk::ScopedAStatus reportStkServiceIsRunningResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus requestIccSimAuthenticationResponse(
+            const RadioResponseInfo& info, const IccIoResult& result) override;
+
+    virtual ndk::ScopedAStatus sendEnvelopeResponse(const RadioResponseInfo& info,
+                                                    const std::string& commandResponse) override;
+
+    virtual ndk::ScopedAStatus sendEnvelopeWithStatusResponse(const RadioResponseInfo& info,
+                                                              const IccIoResult& iccIo) override;
+
+    virtual ndk::ScopedAStatus sendTerminalResponseToSimResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setAllowedCarriersResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCarrierInfoForImsiEncryptionResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCdmaSubscriptionSourceResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setFacilityLockForAppResponse(const RadioResponseInfo& info,
+                                                             int32_t retry) override;
+
+    virtual ndk::ScopedAStatus setSimCardPowerResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setUiccSubscriptionResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus supplyIccPin2ForAppResponse(const RadioResponseInfo& info,
+                                                           int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus supplyIccPinForAppResponse(const RadioResponseInfo& info,
+                                                          int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus supplyIccPuk2ForAppResponse(const RadioResponseInfo& info,
+                                                           int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus supplyIccPukForAppResponse(const RadioResponseInfo& info,
+                                                          int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus supplySimDepersonalizationResponse(
+            const RadioResponseInfo& info, PersoSubstate persoType,
+            int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus updateSimPhonebookRecordsResponse(
+            const RadioResponseInfo& info, int32_t updatedRecordIndex) override;
+};
+
+/* Callback class for radio SIM indication */
+class RadioSimIndication : public BnRadioSimIndication {
+  protected:
+    RadioSimTest& parent_sim;
+
+  public:
+    RadioSimIndication(RadioSimTest& parent_sim);
+    virtual ~RadioSimIndication() = default;
+
+    virtual ndk::ScopedAStatus carrierInfoForImsiEncryption(RadioIndicationType info) override;
+
+    virtual ndk::ScopedAStatus cdmaSubscriptionSourceChanged(
+            RadioIndicationType type, CdmaSubscriptionSource cdmaSource) override;
+
+    virtual ndk::ScopedAStatus simPhonebookChanged(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus simPhonebookRecordsReceived(
+            RadioIndicationType type, PbReceivedStatus status,
+            const std::vector<PhonebookRecordInfo>& records) override;
+
+    virtual ndk::ScopedAStatus simRefresh(RadioIndicationType type,
+                                          const SimRefreshResult& refreshResult) override;
+
+    virtual ndk::ScopedAStatus simStatusChanged(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus stkEventNotify(RadioIndicationType type,
+                                              const std::string& cmd) override;
+
+    virtual ndk::ScopedAStatus stkProactiveCommand(RadioIndicationType type,
+                                                   const std::string& cmd) override;
+
+    virtual ndk::ScopedAStatus stkSessionEnd(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus subscriptionStatusChanged(RadioIndicationType type,
+                                                         bool activate) override;
+
+    virtual ndk::ScopedAStatus uiccApplicationsEnablementChanged(RadioIndicationType type,
+                                                                 bool enabled) override;
+};
+
+// The main test class for Radio AIDL SIM.
+class RadioSimTest : public ::testing::TestWithParam<std::string>, public RadioResponseWaiter {
+  protected:
+    /* Update Sim Card Status */
+    virtual ndk::ScopedAStatus updateSimCardStatus();
+
+  public:
+    virtual void SetUp() override;
+
+    /* radio SIM service handle */
+    std::shared_ptr<IRadioSim> radio_sim;
+    /* radio SIM response handle */
+    std::shared_ptr<RadioSimResponse> radioRsp_sim;
+    /* radio SIM indication handle */
+    std::shared_ptr<RadioSimIndication> radioInd_sim;
+};
diff --git a/radio/aidl/vts/radio_voice_indication.cpp b/radio/aidl/vts/radio_voice_indication.cpp
new file mode 100644
index 0000000..2c46817
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_indication.cpp
@@ -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.
+ */
+
+#include "radio_voice_utils.h"
+
+RadioVoiceIndication::RadioVoiceIndication(RadioVoiceTest& parent) : parent_voice(parent) {}
+
+ndk::ScopedAStatus RadioVoiceIndication::callRing(RadioIndicationType /*type*/, bool /*isGsm*/,
+                                                  const CdmaSignalInfoRecord& /*record*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::callStateChanged(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::cdmaCallWaiting(
+        RadioIndicationType /*type*/, const CdmaCallWaiting& /*callWaitingRecord*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::cdmaInfoRec(
+        RadioIndicationType /*type*/, const std::vector<CdmaInformationRecord>& /*records*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::cdmaOtaProvisionStatus(RadioIndicationType /*type*/,
+                                                                CdmaOtaProvisionStatus /*status*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::currentEmergencyNumberList(
+        RadioIndicationType /*type*/, const std::vector<EmergencyNumber>& /*emergencyNumberList*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::enterEmergencyCallbackMode(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::exitEmergencyCallbackMode(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::indicateRingbackTone(RadioIndicationType /*type*/,
+                                                              bool /*start*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::onSupplementaryServiceIndication(
+        RadioIndicationType /*type*/, const StkCcUnsolSsResult& /*ss*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::resendIncallMute(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::srvccStateNotify(RadioIndicationType /*type*/,
+                                                          SrvccState /*state*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::stkCallControlAlphaNotify(RadioIndicationType /*type*/,
+                                                                   const std::string& /*alpha*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::stkCallSetup(RadioIndicationType /*type*/,
+                                                      int64_t /*timeout*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_voice_response.cpp b/radio/aidl/vts/radio_voice_response.cpp
new file mode 100644
index 0000000..ca350c6
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_response.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_voice_utils.h"
+
+RadioVoiceResponse::RadioVoiceResponse(RadioResponseWaiter& parent) : parent_voice(parent) {}
+
+ndk::ScopedAStatus RadioVoiceResponse::acceptCallResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::conferenceResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::dialResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::emergencyDialResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::exitEmergencyCallbackModeResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::explicitCallTransferResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getCallForwardStatusResponse(
+        const RadioResponseInfo& /*info*/,
+        const std::vector<CallForwardInfo>& /*callForwardInfos*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getCallWaitingResponse(const RadioResponseInfo& /*info*/,
+                                                              bool /*enable*/,
+                                                              int32_t /*serviceClass*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getClipResponse(const RadioResponseInfo& /*info*/,
+                                                       ClipStatus /*status*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getClirResponse(const RadioResponseInfo& /*info*/,
+                                                       int32_t /*n*/, int32_t /*m*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getCurrentCallsResponse(const RadioResponseInfo& info,
+                                                               const std::vector<Call>& calls) {
+    rspInfo = info;
+    currentCalls = calls;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getLastCallFailCauseResponse(
+        const RadioResponseInfo& /*info*/, const LastCallFailCauseInfo& /*failCauseInfo*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getMuteResponse(const RadioResponseInfo& /*info*/,
+                                                       bool /*enable*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getPreferredVoicePrivacyResponse(
+        const RadioResponseInfo& /*info*/, bool /*enable*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getTtyModeResponse(const RadioResponseInfo& /*info*/,
+                                                          TtyMode /*mode*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::handleStkCallSetupRequestFromSimResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::hangupConnectionResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::hangupForegroundResumeBackgroundResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::hangupWaitingOrBackgroundResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::isVoNrEnabledResponse(const RadioResponseInfo& /*info*/,
+                                                             bool /*enabled*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::rejectCallResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::sendBurstDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::sendCdmaFeatureCodeResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::sendDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::separateConnectionResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setCallForwardResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setCallWaitingResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setClirResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setMuteResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setPreferredVoicePrivacyResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setTtyModeResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setVoNrEnabledResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::startDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::stopDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::switchWaitingOrHoldingAndActiveResponse(
+        const RadioResponseInfo& /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_voice_test.cpp b/radio/aidl/vts/radio_voice_test.cpp
new file mode 100644
index 0000000..201f14c
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_test.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_voice_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioVoiceTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_voice = IRadioVoice::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_voice.get());
+
+    radioRsp_voice = ndk::SharedRefBase::make<RadioVoiceResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_voice.get());
+
+    count_ = 0;
+
+    radioInd_voice = ndk::SharedRefBase::make<RadioVoiceIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_voice.get());
+
+    radio_voice->setResponseFunctions(radioRsp_voice, radioInd_voice);
+
+    // Assert IRadioConfig exists before testing
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
+            aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
+                    ndk::SpAIBinder(AServiceManager_waitForService(
+                            "android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radioConfig.get());
+}
+
+ndk::ScopedAStatus RadioVoiceTest::clearPotentialEstablishedCalls() {
+    // Get the current call Id to hangup the established emergency call.
+    serial = GetRandomSerialNumber();
+    radio_voice->getCurrentCalls(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+
+    // Hang up to disconnect the established call channels.
+    for (const Call& call : radioRsp_voice->currentCalls) {
+        serial = GetRandomSerialNumber();
+        radio_voice->hangup(serial, call.index);
+        ALOGI("Hang up to disconnect the established call channel: %d", call.index);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        // Give some time for modem to disconnect the established call channel.
+        sleep(MODEM_EMERGENCY_CALL_DISCONNECT_TIME);
+    }
+
+    // Verify there are no more current calls.
+    serial = GetRandomSerialNumber();
+    radio_voice->getCurrentCalls(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(0, radioRsp_voice->currentCalls.size());
+    return ndk::ScopedAStatus::ok();
+}
+
+/*
+ * Test IRadioVoice.emergencyDial() for the response returned.
+ */
+TEST_P(RadioVoiceTest, emergencyDial) {
+    if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+        ALOGI("Skipping emergencyDial because voice call is not supported in device");
+        return;
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+        return;
+    } else {
+        ALOGI("Running emergencyDial because voice call is supported in device");
+    }
+
+    serial = GetRandomSerialNumber();
+
+    Dial dialInfo;
+    dialInfo.address = std::string("911");
+    EmergencyServiceCategory categories = EmergencyServiceCategory::UNSPECIFIED;
+    std::vector<std::string> urns = {""};
+    EmergencyCallRouting routing = EmergencyCallRouting::UNKNOWN;
+
+    ndk::ScopedAStatus res =
+            radio_voice->emergencyDial(serial, dialInfo, categories, urns, routing, true, true);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    ALOGI("emergencyDial, rspInfo.error = %s\n", toString(radioRsp_voice->rspInfo.error).c_str());
+
+    RadioError rspEmergencyDial = radioRsp_voice->rspInfo.error;
+    // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+    // or Emergency_Only.
+    if (isDsDsEnabled() || isTsTsEnabled()) {
+        // TODO(b/210712359): maybe create a local RadioNetwork instance
+        /**
+        serial = GetRandomSerialNumber();
+        radio_v1_6->getVoiceRegistrationState(serial);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        if (isVoiceEmergencyOnly(radioRsp_v1_6->voiceRegResp.regState) ||
+            isVoiceInService(radioRsp_v1_6->voiceRegResp.regState)) {
+            EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+        }
+        **/
+    } else {
+        EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+    }
+
+    // Give some time for modem to establish the emergency call channel.
+    sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+    // Disconnect all the potential established calls to prevent them affecting other tests.
+    clearPotentialEstablishedCalls();
+}
+
+/*
+ * Test IRadioVoice.emergencyDial() with specified service and its response returned.
+ */
+TEST_P(RadioVoiceTest, emergencyDial_withServices) {
+    if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+        ALOGI("Skipping emergencyDial because voice call is not supported in device");
+        return;
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+        return;
+    } else {
+        ALOGI("Running emergencyDial because voice call is supported in device");
+    }
+
+    serial = GetRandomSerialNumber();
+
+    Dial dialInfo;
+    dialInfo.address = std::string("911");
+    EmergencyServiceCategory categories = EmergencyServiceCategory::AMBULANCE;
+    std::vector<std::string> urns = {"urn:service:sos.ambulance"};
+    EmergencyCallRouting routing = EmergencyCallRouting::UNKNOWN;
+
+    ndk::ScopedAStatus res =
+            radio_voice->emergencyDial(serial, dialInfo, categories, urns, routing, true, true);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    ALOGI("emergencyDial_withServices, rspInfo.error = %s\n",
+          toString(radioRsp_voice->rspInfo.error).c_str());
+    RadioError rspEmergencyDial = radioRsp_voice->rspInfo.error;
+
+    // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+    // or Emergency_Only.
+    if (isDsDsEnabled() || isTsTsEnabled()) {
+        // TODO(b/210712359): maybe create a local RadioNetwork instance
+        /**
+        serial = GetRandomSerialNumber();
+        radio_v1_6->getVoiceRegistrationState_1_6(serial);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        if (isVoiceEmergencyOnly(radioRsp_v1_6->voiceRegResp.regState) ||
+            isVoiceInService(radioRsp_v1_6->voiceRegResp.regState)) {
+            EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+        }
+        **/
+    } else {
+        EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+    }
+    // Give some time for modem to establish the emergency call channel.
+    sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+    // Disconnect all the potential established calls to prevent them affecting other tests.
+    clearPotentialEstablishedCalls();
+}
+
+/*
+ * Test IRadioVoice.emergencyDial() with known emergency call routing and its response returned.
+ */
+TEST_P(RadioVoiceTest, emergencyDial_withEmergencyRouting) {
+    if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+        ALOGI("Skipping emergencyDial because voice call is not supported in device");
+        return;
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+        return;
+    } else {
+        ALOGI("Running emergencyDial because voice call is supported in device");
+    }
+
+    serial = GetRandomSerialNumber();
+
+    Dial dialInfo;
+    dialInfo.address = std::string("911");
+    EmergencyServiceCategory categories = EmergencyServiceCategory::UNSPECIFIED;
+    std::vector<std::string> urns = {""};
+    EmergencyCallRouting routing = EmergencyCallRouting::EMERGENCY;
+
+    ndk::ScopedAStatus res =
+            radio_voice->emergencyDial(serial, dialInfo, categories, urns, routing, true, true);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    ALOGI("emergencyDial_withEmergencyRouting, rspInfo.error = %s\n",
+          toString(radioRsp_voice->rspInfo.error).c_str());
+    RadioError rspEmergencyDial = radioRsp_voice->rspInfo.error;
+
+    // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+    // or Emergency_Only.
+    if (isDsDsEnabled() || isTsTsEnabled()) {
+        // TODO(b/210712359): maybe create a local RadioNetwork instance
+        /**
+        serial = GetRandomSerialNumber();
+        radio_v1_6->getVoiceRegistrationState_1_6(serial);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        if (isVoiceEmergencyOnly(radioRsp_v1_6->voiceRegResp.regState) ||
+            isVoiceInService(radioRsp_v1_6->voiceRegResp.regState)) {
+            EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+        }
+        **/
+    } else {
+        EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+    }
+
+    // Give some time for modem to establish the emergency call channel.
+    sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+    // Disconnect all the potential established calls to prevent them affecting other tests.
+    clearPotentialEstablishedCalls();
+}
+
+/*
+ * Test IRadioVoice.getCurrentCalls() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getCurrentCalls) {
+    serial = GetRandomSerialNumber();
+    radio_voice->getCurrentCalls(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_voice->rspInfo.error);
+}
diff --git a/radio/aidl/vts/radio_voice_utils.h b/radio/aidl/vts/radio_voice_utils.h
new file mode 100644
index 0000000..a676a7f
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_utils.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/voice/BnRadioVoiceIndication.h>
+#include <aidl/android/hardware/radio/voice/BnRadioVoiceResponse.h>
+#include <aidl/android/hardware/radio/voice/IRadioVoice.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::voice;
+
+class RadioVoiceTest;
+
+/* Callback class for radio voice response */
+class RadioVoiceResponse : public BnRadioVoiceResponse {
+  protected:
+    RadioResponseWaiter& parent_voice;
+
+  public:
+    RadioVoiceResponse(RadioResponseWaiter& parent_voice);
+    virtual ~RadioVoiceResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    std::vector<Call> currentCalls;
+
+    virtual ndk::ScopedAStatus acceptCallResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus conferenceResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus dialResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus emergencyDialResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus exitEmergencyCallbackModeResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus explicitCallTransferResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getCallForwardStatusResponse(
+            const RadioResponseInfo& info,
+            const std::vector<CallForwardInfo>& call_forwardInfos) override;
+
+    virtual ndk::ScopedAStatus getCallWaitingResponse(const RadioResponseInfo& info, bool enable,
+                                                      int32_t serviceClass) override;
+
+    virtual ndk::ScopedAStatus getClipResponse(const RadioResponseInfo& info,
+                                               ClipStatus status) override;
+
+    virtual ndk::ScopedAStatus getClirResponse(const RadioResponseInfo& info, int32_t n,
+                                               int32_t m) override;
+
+    virtual ndk::ScopedAStatus getCurrentCallsResponse(const RadioResponseInfo& info,
+                                                       const std::vector<Call>& calls) override;
+
+    virtual ndk::ScopedAStatus getLastCallFailCauseResponse(
+            const RadioResponseInfo& info, const LastCallFailCauseInfo& failCauseInfo) override;
+
+    virtual ndk::ScopedAStatus getMuteResponse(const RadioResponseInfo& info, bool enable) override;
+
+    virtual ndk::ScopedAStatus getPreferredVoicePrivacyResponse(const RadioResponseInfo& info,
+                                                                bool enable) override;
+
+    virtual ndk::ScopedAStatus getTtyModeResponse(const RadioResponseInfo& info,
+                                                  TtyMode mode) override;
+
+    virtual ndk::ScopedAStatus handleStkCallSetupRequestFromSimResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus hangupConnectionResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus hangupForegroundResumeBackgroundResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus hangupWaitingOrBackgroundResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus isVoNrEnabledResponse(const RadioResponseInfo& info,
+                                                     bool enable) override;
+
+    virtual ndk::ScopedAStatus rejectCallResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendBurstDtmfResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendCdmaFeatureCodeResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendDtmfResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus separateConnectionResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCallForwardResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCallWaitingResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setClirResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setMuteResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setPreferredVoicePrivacyResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setTtyModeResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setVoNrEnabledResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus startDtmfResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus stopDtmfResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus switchWaitingOrHoldingAndActiveResponse(
+            const RadioResponseInfo& info) override;
+};
+
+/* Callback class for radio voice indication */
+class RadioVoiceIndication : public BnRadioVoiceIndication {
+  protected:
+    RadioVoiceTest& parent_voice;
+
+  public:
+    RadioVoiceIndication(RadioVoiceTest& parent_voice);
+    virtual ~RadioVoiceIndication() = default;
+
+    virtual ndk::ScopedAStatus callRing(RadioIndicationType type, bool isGsm,
+                                        const CdmaSignalInfoRecord& record) override;
+
+    virtual ndk::ScopedAStatus callStateChanged(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus cdmaCallWaiting(RadioIndicationType type,
+                                               const CdmaCallWaiting& callWaitingRecord) override;
+
+    virtual ndk::ScopedAStatus cdmaInfoRec(
+            RadioIndicationType type, const std::vector<CdmaInformationRecord>& records) override;
+
+    virtual ndk::ScopedAStatus cdmaOtaProvisionStatus(RadioIndicationType type,
+                                                      CdmaOtaProvisionStatus status) override;
+
+    virtual ndk::ScopedAStatus currentEmergencyNumberList(
+            RadioIndicationType type,
+            const std::vector<EmergencyNumber>& emergencyNumberList) override;
+
+    virtual ndk::ScopedAStatus enterEmergencyCallbackMode(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus exitEmergencyCallbackMode(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus indicateRingbackTone(RadioIndicationType type, bool start) override;
+
+    virtual ndk::ScopedAStatus onSupplementaryServiceIndication(
+            RadioIndicationType type, const StkCcUnsolSsResult& ss) override;
+
+    virtual ndk::ScopedAStatus resendIncallMute(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus srvccStateNotify(RadioIndicationType type,
+                                                SrvccState state) override;
+
+    virtual ndk::ScopedAStatus stkCallControlAlphaNotify(RadioIndicationType type,
+                                                         const std::string& alpha) override;
+
+    virtual ndk::ScopedAStatus stkCallSetup(RadioIndicationType type, int64_t timeout) override;
+};
+
+// The main test class for Radio AIDL Voice.
+class RadioVoiceTest : public ::testing::TestWithParam<std::string>, public RadioResponseWaiter {
+  protected:
+    /* Clear Potential Established Calls */
+    virtual ndk::ScopedAStatus clearPotentialEstablishedCalls();
+
+  public:
+    virtual void SetUp() override;
+
+    /* radio voice service handle */
+    std::shared_ptr<IRadioVoice> radio_voice;
+    /* radio voice response handle */
+    std::shared_ptr<RadioVoiceResponse> radioRsp_voice;
+    /* radio voice indication handle */
+    std::shared_ptr<RadioVoiceIndication> radioInd_voice;
+};
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 5b80b6f..dd3719b 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -4954,6 +4954,49 @@
 }
 
 /*
+ * EncryptionOperationsTest.AesCbcZeroInputSuccessb
+ *
+ * Verifies that keymaster generates correct output on zero-input with
+ * NonePadding mode
+ */
+TEST_P(EncryptionOperationsTest, AesCbcZeroInputSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .AesEncryptionKey(128)
+                                                 .BlockMode(BlockMode::CBC)
+                                                 .Padding(PaddingMode::NONE, PaddingMode::PKCS7)));
+
+    // Zero input message
+    string message = "";
+    for (auto padding : {PaddingMode::NONE, PaddingMode::PKCS7}) {
+        auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(padding);
+        AuthorizationSet out_params;
+        string ciphertext1 = EncryptMessage(message, params, &out_params);
+        vector<uint8_t> iv1 = CopyIv(out_params);
+        if (padding == PaddingMode::NONE)
+            EXPECT_EQ(message.size(), ciphertext1.size()) << "PaddingMode: " << padding;
+        else
+            EXPECT_EQ(message.size(), ciphertext1.size() - 16) << "PaddingMode: " << padding;
+
+        out_params.Clear();
+
+        string ciphertext2 = EncryptMessage(message, params, &out_params);
+        vector<uint8_t> iv2 = CopyIv(out_params);
+        if (padding == PaddingMode::NONE)
+            EXPECT_EQ(message.size(), ciphertext2.size()) << "PaddingMode: " << padding;
+        else
+            EXPECT_EQ(message.size(), ciphertext2.size() - 16) << "PaddingMode: " << padding;
+
+        // IVs should be random
+        EXPECT_NE(iv1, iv2) << "PaddingMode: " << padding;
+
+        params.push_back(TAG_NONCE, iv1);
+        string plaintext = DecryptMessage(ciphertext1, params);
+        EXPECT_EQ(message, plaintext) << "PaddingMode: " << padding;
+    }
+}
+
+/*
  * EncryptionOperationsTest.AesCallerNonce
  *
  * Verifies that AES caller-provided nonces work correctly.
@@ -6594,7 +6637,7 @@
     size_t i;
 
     for (i = 0; i < max_operations; i++) {
-        result = Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, op_handles[i]);
+        result = Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params, op_handles[i]);
         if (ErrorCode::OK != result) {
             break;
         }
@@ -6602,12 +6645,12 @@
     EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS, result);
     // Try again just in case there's a weird overflow bug
     EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
-              Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+              Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
     for (size_t j = 0; j < i; j++) {
         EXPECT_EQ(ErrorCode::OK, Abort(op_handles[j]))
                 << "Aboort failed for i = " << j << std::endl;
     }
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
     AbortIfNeeded();
 }
 
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
index aca6961..c69f32a 100644
--- a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
@@ -25,7 +25,7 @@
 using ::android::hardware::sensors::V1_0::Result;
 using ::android::hardware::sensors::V1_0::SensorInfo;
 
-void SensorsHidlEnvironmentV1_0::HidlTearDown() {
+void SensorsHidlEnvironmentV1_0::TearDown() {
     mStopThread = true;
     if (mPollThread.joinable()) {
         mPollThread.detach();
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
index 168777d..b802e6c 100644
--- a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
 #define ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
 
-#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
+#include "sensors-vts-utils/SensorsVtsEnvironmentBase.h"
 
 #include <android/hardware/sensors/1.0/ISensors.h>
 #include <android/hardware/sensors/1.0/types.h>
@@ -30,13 +30,13 @@
 
 class SensorsHidlTest;
 class SensorsHidlEnvironmentV1_0
-    : public SensorsHidlEnvironmentBase<::android::hardware::sensors::V1_0::Event> {
+    : public SensorsVtsEnvironmentBase<::android::hardware::sensors::V1_0::Event> {
   public:
-    void HidlTearDown() override;
+    void TearDown() override;
 
     using Event = ::android::hardware::sensors::V1_0::Event;
     SensorsHidlEnvironmentV1_0(const std::string& service_name)
-        : SensorsHidlEnvironmentBase(service_name) {}
+        : SensorsVtsEnvironmentBase(service_name) {}
 
   private:
     friend SensorsHidlTest;
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index d46cf5a..e4fa969 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -39,12 +39,12 @@
   public:
     virtual void SetUp() override {
         mEnvironment = new SensorsHidlEnvironmentV1_0(GetParam());
-        mEnvironment->HidlSetUp();
+        mEnvironment->SetUp();
         // Ensure that we have a valid environment before performing tests
         ASSERT_NE(S(), nullptr);
     }
 
-    virtual void TearDown() override { mEnvironment->HidlTearDown(); }
+    virtual void TearDown() override { mEnvironment->TearDown(); }
 
   protected:
     SensorInfo defaultSensorByType(SensorType type) override;
@@ -81,7 +81,7 @@
 
     inline sp<ISensors>& S() { return mEnvironment->sensors; }
 
-    SensorsHidlEnvironmentBase<Event>* getEnvironment() override { return mEnvironment; }
+    SensorsVtsEnvironmentBase<Event>* getEnvironment() override { return mEnvironment; }
 
   private:
     // Test environment for sensors HAL.
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index e212423..d7d061a 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -256,8 +256,8 @@
     // Clear the active direct connections so they are not stopped during TearDown
     auto handles = mDirectChannelHandles;
     mDirectChannelHandles.clear();
-    getEnvironment()->HidlTearDown();
-    getEnvironment()->HidlSetUp();
+    getEnvironment()->TearDown();
+    getEnvironment()->SetUp();
     if (HasFatalFailure()) {
         return;  // Exit early if resetting the environment failed
     }
diff --git a/sensors/common/utils/convertV2_1.h b/sensors/common/utils/convertV2_1.h
index 9231011..00359043 100644
--- a/sensors/common/utils/convertV2_1.h
+++ b/sensors/common/utils/convertV2_1.h
@@ -77,6 +77,25 @@
     return reinterpret_cast<const hidl_vec<V1_0::SensorInfo>&>(infos);
 }
 
+inline void convertToSensor(const V2_1::SensorInfo& src, sensor_t* dst) {
+    dst->name = strdup(src.name.c_str());
+    dst->vendor = strdup(src.vendor.c_str());
+    dst->version = src.version;
+    dst->handle = src.sensorHandle;
+    dst->type = (int)src.type;
+    dst->maxRange = src.maxRange;
+    dst->resolution = src.resolution;
+    dst->power = src.power;
+    dst->minDelay = src.minDelay;
+    dst->fifoReservedEventCount = src.fifoReservedEventCount;
+    dst->fifoMaxEventCount = src.fifoMaxEventCount;
+    dst->stringType = strdup(src.typeAsString.c_str());
+    dst->requiredPermission = strdup(src.requiredPermission.c_str());
+    dst->maxDelay = src.maxDelay;
+    dst->flags = src.flags;
+    dst->reserved[0] = dst->reserved[1] = 0;
+}
+
 inline void convertFromSensorEvent(const sensors_event_t& src, V2_1::Event* dst) {
     switch ((SensorType)src.type) {
         case SensorType::HINGE_ANGLE:
diff --git a/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.cpp b/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.cpp
index a8c2513..d395820 100644
--- a/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.cpp
+++ b/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.cpp
@@ -103,7 +103,7 @@
     return succeed;
 }
 
-void SensorsHidlEnvironmentV2_X::HidlTearDown() {
+void SensorsHidlEnvironmentV2_X::TearDown() {
     mStopThread = true;
 
     if (mEventQueueFlag != nullptr) {
diff --git a/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.h b/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.h
index 01f451f..5fe4d8b 100644
--- a/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.h
+++ b/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.h
@@ -18,7 +18,7 @@
 #define ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_X_H
 
 #include "ISensorsWrapper.h"
-#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
+#include "sensors-vts-utils/SensorsVtsEnvironmentBase.h"
 
 #include <android/hardware/sensors/2.1/ISensors.h>
 #include <android/hardware/sensors/2.1/types.h>
@@ -46,14 +46,14 @@
 };
 
 class SensorsHidlEnvironmentV2_X
-    : public SensorsHidlEnvironmentBase<::android::hardware::sensors::V2_1::Event> {
+    : public SensorsVtsEnvironmentBase<::android::hardware::sensors::V2_1::Event> {
   public:
-    virtual void HidlTearDown() override;
+    virtual void TearDown() override;
 
   protected:
     friend SensorsHidlTest;
     SensorsHidlEnvironmentV2_X(const std::string& service_name)
-        : SensorsHidlEnvironmentBase(service_name), mEventQueueFlag(nullptr) {}
+        : SensorsVtsEnvironmentBase(service_name), mEventQueueFlag(nullptr) {}
 
     /**
      * Resets the HAL with new FMQs and a new Event Flag
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index ea5dc70..7e22b19 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -170,12 +170,12 @@
   public:
     virtual void SetUp() override {
         mEnvironment = new SensorsHidlEnvironmentV2_X(GetParam());
-        mEnvironment->HidlSetUp();
+        mEnvironment->SetUp();
         // Ensure that we have a valid environment before performing tests
         ASSERT_NE(getSensors(), nullptr);
     }
 
-    virtual void TearDown() override { mEnvironment->HidlTearDown(); }
+    virtual void TearDown() override { mEnvironment->TearDown(); }
 
   protected:
     SensorInfoType defaultSensorByType(SensorTypeVersion type) override;
@@ -216,7 +216,7 @@
 
     inline sp<ISensorsWrapperBase>& getSensors() { return mEnvironment->mSensors; }
 
-    SensorsHidlEnvironmentBase<EventType>* getEnvironment() override { return mEnvironment; }
+    SensorsVtsEnvironmentBase<EventType>* getEnvironment() override { return mEnvironment; }
 
     // Test helpers
     void runSingleFlushTest(const std::vector<SensorInfoType>& sensors, bool activateSensor,
@@ -530,32 +530,31 @@
     // Create a new environment that calls initialize()
     std::unique_ptr<SensorsHidlEnvironmentTest> newEnv =
             std::make_unique<SensorsHidlEnvironmentTest>(GetParam());
-    newEnv->HidlSetUp();
+    newEnv->SetUp();
     if (HasFatalFailure()) {
         return;  // Exit early if setting up the new environment failed
     }
 
     activateAllSensors(true);
     // Verify that the old environment does not receive any events
-    EXPECT_EQ(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), 0);
+    EXPECT_EQ(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), 0);
     // Verify that the new event queue receives sensor events
-    EXPECT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents, newEnv.get(), newEnv.get()).size(),
-              kNumEvents);
+    EXPECT_GE(newEnv.get()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents);
     activateAllSensors(false);
 
     // Cleanup the test environment
-    newEnv->HidlTearDown();
+    newEnv->TearDown();
 
     // Restore the test environment for future tests
-    getEnvironment()->HidlTearDown();
-    getEnvironment()->HidlSetUp();
+    getEnvironment()->TearDown();
+    getEnvironment()->SetUp();
     if (HasFatalFailure()) {
         return;  // Exit early if resetting the environment failed
     }
 
     // Ensure that the original environment is receiving events
     activateAllSensors(true);
-    EXPECT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents);
+    EXPECT_GE(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents);
     activateAllSensors(false);
 }
 
@@ -565,21 +564,21 @@
     // Verify that events are received
     constexpr useconds_t kCollectionTimeoutUs = 1000 * 1000;  // 1s
     constexpr int32_t kNumEvents = 1;
-    ASSERT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), kNumEvents);
+    ASSERT_GE(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents);
 
     // Clear the active sensor handles so they are not disabled during TearDown
     auto handles = mSensorHandles;
     mSensorHandles.clear();
-    getEnvironment()->HidlTearDown();
-    getEnvironment()->HidlSetUp();
+    getEnvironment()->TearDown();
+    getEnvironment()->SetUp();
     if (HasFatalFailure()) {
         return;  // Exit early if resetting the environment failed
     }
 
     // Verify no events are received until sensors are re-activated
-    ASSERT_EQ(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), 0);
+    ASSERT_EQ(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), 0);
     activateAllSensors(true);
-    ASSERT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), kNumEvents);
+    ASSERT_GE(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents);
 
     // Disable sensors
     activateAllSensors(false);
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
deleted file mode 100644
index 19dfbe5..0000000
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
-#define ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
-
-#include <gtest/gtest.h>
-
-#include <atomic>
-#include <memory>
-#include <mutex>
-#include <thread>
-#include <vector>
-
-template <class Event>
-class IEventCallback {
-  public:
-    virtual ~IEventCallback() = default;
-    virtual void onEvent(const Event& event) = 0;
-};
-
-template <class Event>
-class SensorsHidlEnvironmentBase {
-  public:
-    virtual void HidlSetUp() {
-        ASSERT_TRUE(resetHal()) << "could not get hidl service";
-
-        mCollectionEnabled = false;
-        startPollingThread();
-
-        // In case framework just stopped for test and there is sensor events in the pipe,
-        // wait some time for those events to be cleared to avoid them messing up the test.
-        std::this_thread::sleep_for(std::chrono::seconds(3));
-    }
-
-    virtual void HidlTearDown() = 0;
-
-    // Get and clear all events collected so far (like "cat" shell command).
-    // If output is nullptr, it clears all collected events.
-    void catEvents(std::vector<Event>* output) {
-        std::lock_guard<std::mutex> lock(mEventsMutex);
-        if (output) {
-            output->insert(output->end(), mEvents.begin(), mEvents.end());
-        }
-        mEvents.clear();
-    }
-
-    // set sensor event collection status
-    void setCollection(bool enable) {
-        std::lock_guard<std::mutex> lock(mEventsMutex);
-        mCollectionEnabled = enable;
-    }
-
-    void registerCallback(IEventCallback<Event>* callback) {
-        std::lock_guard<std::mutex> lock(mEventsMutex);
-        mCallback = callback;
-    }
-
-    void unregisterCallback() {
-        std::lock_guard<std::mutex> lock(mEventsMutex);
-        mCallback = nullptr;
-    }
-
-   protected:
-     SensorsHidlEnvironmentBase(const std::string& service_name)
-         : mCollectionEnabled(false), mCallback(nullptr) {
-         mServiceName = service_name;
-     }
-     virtual ~SensorsHidlEnvironmentBase(){};
-
-     void addEvent(const Event& ev) {
-         std::lock_guard<std::mutex> lock(mEventsMutex);
-         if (mCollectionEnabled) {
-             mEvents.push_back(ev);
-         }
-
-         if (mCallback != nullptr) {
-             mCallback->onEvent(ev);
-         }
-     }
-
-     virtual void startPollingThread() = 0;
-     virtual bool resetHal() = 0;
-
-     std::string mServiceName;
-     bool mCollectionEnabled;
-     std::atomic_bool mStopThread;
-     std::thread mPollThread;
-     std::vector<Event> mEvents;
-     std::mutex mEventsMutex;
-
-     IEventCallback<Event>* mCallback;
-
-     GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentBase<Event>);
-};
-
-#endif  // ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
\ No newline at end of file
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
index af14009..f3cbd78 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
@@ -18,8 +18,8 @@
 #define ANDROID_SENSORS_HIDL_TEST_BASE_H
 
 #include "sensors-vts-utils/SensorEventsChecker.h"
-#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
 #include "sensors-vts-utils/SensorsTestSharedMemory.h"
+#include "sensors-vts-utils/SensorsVtsEnvironmentBase.h"
 
 #include <android/hardware/sensors/1.0/ISensors.h>
 #include <android/hardware/sensors/1.0/types.h>
@@ -163,7 +163,7 @@
         : mAccelNormChecker(Vec3NormChecker<EventType>::byNominal(GRAVITY_EARTH, 1.0f /*m/s^2*/)),
           mGyroNormChecker(Vec3NormChecker<EventType>::byNominal(0.f, 0.1f /*rad/s*/)) {}
 
-    virtual SensorsHidlEnvironmentBase<EventType>* getEnvironment() = 0;
+    virtual SensorsVtsEnvironmentBase<EventType>* getEnvironment() = 0;
 
     virtual void SetUp() override {}
 
@@ -198,49 +198,6 @@
                                             RateLevel rate,
                                             ISensors::configDirectReport_cb _hidl_cb) = 0;
 
-    std::vector<EventType> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
-                                         bool clearBeforeStart = true,
-                                         bool changeCollection = true) {
-        return collectEvents(timeLimitUs, nEventLimit, getEnvironment(), clearBeforeStart,
-                             changeCollection);
-    }
-
-    std::vector<EventType> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
-                                         SensorsHidlEnvironmentBase<EventType>* environment,
-                                         bool clearBeforeStart = true,
-                                         bool changeCollection = true) {
-        std::vector<EventType> events;
-        constexpr useconds_t SLEEP_GRANULARITY = 100 * 1000;  // granularity 100 ms
-
-        ALOGI("collect max of %zu events for %d us, clearBeforeStart %d", nEventLimit, timeLimitUs,
-              clearBeforeStart);
-
-        if (changeCollection) {
-            environment->setCollection(true);
-        }
-        if (clearBeforeStart) {
-            environment->catEvents(nullptr);
-        }
-
-        while (timeLimitUs > 0) {
-            useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs);
-            usleep(duration);
-            timeLimitUs -= duration;
-
-            environment->catEvents(&events);
-            if (events.size() >= nEventLimit) {
-                break;
-            }
-            ALOGV("time to go = %d, events to go = %d", (int)timeLimitUs,
-                  (int)(nEventLimit - events.size()));
-        }
-
-        if (changeCollection) {
-            environment->setCollection(false);
-        }
-        return events;
-    }
-
     void testStreamingOperation(SensorTypeVersion type, std::chrono::nanoseconds samplingPeriod,
                                 std::chrono::seconds duration,
                                 const SensorEventsChecker<EventType>& checker) {
@@ -268,7 +225,7 @@
 
         ASSERT_EQ(batch(handle, samplingPeriodInNs, batchingPeriodInNs), Result::OK);
         ASSERT_EQ(activate(handle, 1), Result::OK);
-        events = collectEvents(minTimeUs, minNEvent, getEnvironment(), true /*clearBeforeStart*/);
+        events = getEnvironment()->collectEvents(minTimeUs, minNEvent, true /*clearBeforeStart*/);
         ASSERT_EQ(activate(handle, 0), Result::OK);
 
         ALOGI("Collected %zu samples", events.size());
@@ -335,13 +292,13 @@
         ASSERT_EQ(activate(handle, 1), Result::OK);
 
         usleep(500000);  // sleep 0.5 sec to wait for change rate to happen
-        events1 = collectEvents(collectionTimeoutUs, minNEvent, getEnvironment());
+        events1 = getEnvironment()->collectEvents(collectionTimeoutUs, minNEvent);
 
         // second collection, without stopping the sensor
         ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK);
 
         usleep(500000);  // sleep 0.5 sec to wait for change rate to happen
-        events2 = collectEvents(collectionTimeoutUs, minNEvent, getEnvironment());
+        events2 = getEnvironment()->collectEvents(collectionTimeoutUs, minNEvent);
 
         // end of collection, stop sensor
         ASSERT_EQ(activate(handle, 0), Result::OK);
@@ -447,16 +404,17 @@
 
         getEnvironment()->setCollection(true);
         // clean existing collections
-        collectEvents(0 /*timeLimitUs*/, 0 /*nEventLimit*/, true /*clearBeforeStart*/,
-                      false /*change collection*/);
+        getEnvironment()->collectEvents(0 /*timeLimitUs*/, 0 /*nEventLimit*/,
+                                        true /*clearBeforeStart*/, false /*change collection*/);
 
         // 0.8 + 0.2 times the batching period
         usleep(batchingPeriodInNs / 1000 * 2 / 10);
         ASSERT_EQ(flush(handle), Result::OK);
 
         // plus some time for the event to deliver
-        events = collectEvents(allowedBatchDeliverTimeNs / 1000, minFifoCount,
-                               false /*clearBeforeStart*/, false /*change collection*/);
+        events = getEnvironment()->collectEvents(allowedBatchDeliverTimeNs / 1000, minFifoCount,
+                                                 false /*clearBeforeStart*/,
+                                                 false /*change collection*/);
 
         getEnvironment()->setCollection(false);
         ASSERT_EQ(activate(handle, 0), Result::OK);
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsVtsEnvironmentBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsVtsEnvironmentBase.h
new file mode 100644
index 0000000..17a96ed
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsVtsEnvironmentBase.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSORS_VTS_ENVIRONMENT_BASE_H
+#define ANDROID_SENSORS_VTS_ENVIRONMENT_BASE_H
+
+#include <gtest/gtest.h>
+
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+#include <log/log.h>
+
+template <class Event>
+class IEventCallback {
+  public:
+    virtual ~IEventCallback() = default;
+    virtual void onEvent(const Event& event) = 0;
+};
+
+template <class Event>
+class SensorsVtsEnvironmentBase {
+  public:
+    virtual void SetUp() {
+        ASSERT_TRUE(resetHal()) << "could not get hidl service";
+
+        mCollectionEnabled = false;
+        startPollingThread();
+
+        // In case framework just stopped for test and there is sensor events in the pipe,
+        // wait some time for those events to be cleared to avoid them messing up the test.
+        std::this_thread::sleep_for(std::chrono::seconds(3));
+    }
+
+    virtual void TearDown() = 0;
+
+    // Get and clear all events collected so far (like "cat" shell command).
+    // If output is nullptr, it clears all collected events.
+    void catEvents(std::vector<Event>* output) {
+        std::lock_guard<std::mutex> lock(mEventsMutex);
+        if (output) {
+            output->insert(output->end(), mEvents.begin(), mEvents.end());
+        }
+        mEvents.clear();
+    }
+
+    // set sensor event collection status
+    void setCollection(bool enable) {
+        std::lock_guard<std::mutex> lock(mEventsMutex);
+        mCollectionEnabled = enable;
+    }
+
+    void registerCallback(IEventCallback<Event>* callback) {
+        std::lock_guard<std::mutex> lock(mEventsMutex);
+        mCallback = callback;
+    }
+
+    void unregisterCallback() {
+        std::lock_guard<std::mutex> lock(mEventsMutex);
+        mCallback = nullptr;
+    }
+
+    std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
+                                     bool clearBeforeStart = true, bool changeCollection = true) {
+        std::vector<Event> events;
+        constexpr useconds_t SLEEP_GRANULARITY = 100 * 1000;  // granularity 100 ms
+
+        ALOGI("collect max of %zu events for %d us, clearBeforeStart %d", nEventLimit, timeLimitUs,
+              clearBeforeStart);
+
+        if (changeCollection) {
+            setCollection(true);
+        }
+        if (clearBeforeStart) {
+            catEvents(nullptr);
+        }
+
+        while (timeLimitUs > 0) {
+            useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs);
+            usleep(duration);
+            timeLimitUs -= duration;
+
+            catEvents(&events);
+            if (events.size() >= nEventLimit) {
+                break;
+            }
+            ALOGV("time to go = %d, events to go = %d", (int)timeLimitUs,
+                  (int)(nEventLimit - events.size()));
+        }
+
+        if (changeCollection) {
+            setCollection(false);
+        }
+        return events;
+    }
+
+  protected:
+    SensorsVtsEnvironmentBase(const std::string& service_name)
+        : mCollectionEnabled(false), mCallback(nullptr) {
+        mServiceName = service_name;
+    }
+    virtual ~SensorsVtsEnvironmentBase(){};
+
+    void addEvent(const Event& ev) {
+        std::lock_guard<std::mutex> lock(mEventsMutex);
+        if (mCollectionEnabled) {
+            mEvents.push_back(ev);
+        }
+
+        if (mCallback != nullptr) {
+            mCallback->onEvent(ev);
+        }
+    }
+
+    virtual void startPollingThread() = 0;
+    virtual bool resetHal() = 0;
+
+    std::string mServiceName;
+    bool mCollectionEnabled;
+    std::atomic_bool mStopThread;
+    std::thread mPollThread;
+    std::vector<Event> mEvents;
+    std::mutex mEventsMutex;
+
+    IEventCallback<Event>* mCallback;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsVtsEnvironmentBase<Event>);
+};
+
+#endif  // ANDROID_SENSORS_VTS_ENVIRONMENT_BASE_H
\ No newline at end of file
diff --git a/soundtrigger/2.3/cli/Android.bp b/soundtrigger/2.3/cli/Android.bp
new file mode 100644
index 0000000..27d7b30
--- /dev/null
+++ b/soundtrigger/2.3/cli/Android.bp
@@ -0,0 +1,17 @@
+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"],
+}
+
+java_binary {
+    name: "sthal_cli_2.3",
+    wrapper: "sthal_cli_2.3",
+    srcs: ["java/**/*.java"],
+    static_libs: [
+        "android.hardware.soundtrigger-V2.3-java",
+    ],
+}
diff --git a/soundtrigger/2.3/cli/OWNERS b/soundtrigger/2.3/cli/OWNERS
new file mode 100644
index 0000000..4fd27f3
--- /dev/null
+++ b/soundtrigger/2.3/cli/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/services/core/java/com/android/server/soundtrigger_middleware/OWNERS
diff --git a/soundtrigger/2.3/cli/java/android/hardware/soundtrigger/V2_3/cli/SthalCli.java b/soundtrigger/2.3/cli/java/android/hardware/soundtrigger/V2_3/cli/SthalCli.java
new file mode 100644
index 0000000..68b04f4
--- /dev/null
+++ b/soundtrigger/2.3/cli/java/android/hardware/soundtrigger/V2_3/cli/SthalCli.java
@@ -0,0 +1,344 @@
+/*
+ * 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.soundtrigger.V2_3.cli;
+
+import android.hardware.soundtrigger.V2_0.PhraseRecognitionExtra;
+import android.hardware.soundtrigger.V2_0.RecognitionMode;
+import android.hardware.soundtrigger.V2_0.SoundModelType;
+import android.hardware.soundtrigger.V2_3.OptionalModelParameterRange;
+import android.hardware.soundtrigger.V2_3.ISoundTriggerHw;
+import android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback;
+import android.os.HidlMemoryUtil;
+import android.os.HwBinder;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+
+import java.util.Scanner;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * This is a quick-and-dirty sound trigger HAL console mock.
+ *
+ * It would only work on userdebug builds.
+ *
+ * When this app is started, it will initially:
+ * - Register a ISoundTriggerHw HAL with an instance name "mock".
+ * - Set a sysprop that tells SoundTriggerMiddlewareService to try to connect to the mock instance
+ * rather than the default one.
+ * - Reboot the real (default) HAL.
+ *
+ * In response to that, SoundTriggerMiddlewareService is going to connect to the mock HAL and resume
+ * normal operation.
+ *
+ * Our mock HAL will print to stdout every call it receives as well as expose a basic set of
+ * operations for sending event callbacks to the client. This allows us to simulate the frameworks
+ * behavior in response to different HAL behaviors.
+ */
+public class SthalCli {
+    private static SoundTriggerImpl mService;
+    private static final Scanner mScanner = new Scanner(System.in);
+
+    public static void main(String[] args) {
+        try {
+            System.out.println("Registering mock STHAL");
+            HwBinder.setTrebleTestingOverride(true);
+            mService = new SoundTriggerImpl();
+            mService.registerAsService("mock");
+
+            System.out.println("Rebooting STHAL");
+            SystemProperties.set("debug.soundtrigger_middleware.use_mock_hal", "2");
+            SystemProperties.set("sys.audio.restart.hal", "1");
+
+            while (processCommand()) ;
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            cleanup();
+        }
+    }
+
+    private static void cleanup() {
+        System.out.println("Cleaning up.");
+        SystemProperties.set("debug.soundtrigger_middleware.use_mock_hal", null);
+        HwBinder.setTrebleTestingOverride(false);
+    }
+
+    private static boolean processCommand() {
+        String line = mScanner.nextLine();
+        String[] tokens = line.split("\\s+");
+        if (tokens.length < 1) {
+            return false;
+        }
+        switch (tokens[0]) {
+            case "q":
+                return false;
+
+            case "r":
+                mService.sendRecognitionEvent(Integer.parseInt(tokens[1]),
+                        Integer.parseInt(tokens[2]));
+                return true;
+
+            case "p":
+                mService.sendPhraseRecognitionEvent(Integer.parseInt(tokens[1]),
+                        Integer.parseInt(tokens[2]));
+                return true;
+
+            case "d":
+                mService.dumpModels();
+                return true;
+
+            case "h":
+                System.out.print("Available commands:\n" + "h - help\n" + "q - quit\n"
+                        + "r <model> <status> - send recognitionEvent\n"
+                        + "p <model> <status> - send phraseRecognitionEvent\n"
+                        + "d - dump models\n");
+
+            default:
+                return true;
+        }
+    }
+
+    private static class SoundTriggerImpl extends ISoundTriggerHw.Stub {
+        static class Model {
+            final ISoundTriggerHwCallback callback;
+            final SoundModel model;
+            final PhraseSoundModel phraseModel;
+            public android.hardware.soundtrigger.V2_3.RecognitionConfig config = null;
+
+            Model(ISoundTriggerHwCallback callback, SoundModel model) {
+                this.callback = callback;
+                this.model = model;
+                this.phraseModel = null;
+            }
+
+            Model(ISoundTriggerHwCallback callback, PhraseSoundModel model) {
+                this.callback = callback;
+                this.model = null;
+                this.phraseModel = model;
+            }
+        }
+
+        private final ConcurrentMap<Integer, Model> mLoadedModels = new ConcurrentHashMap<>();
+        private int mHandleCounter = 1;
+
+        public void dumpModels() {
+            mLoadedModels.forEach((handle, model) -> {
+                System.out.println("+++ Model " + handle);
+                System.out.println("    config = " + model.config);
+                android.hardware.soundtrigger.V2_3.RecognitionConfig recognitionConfig =
+                        model.config;
+                if (recognitionConfig != null) {
+                    System.out.println("    ACTIVE recognitionConfig = " + recognitionConfig);
+                } else {
+                    System.out.println("    INACTIVE");
+                }
+            });
+        }
+
+        public void sendRecognitionEvent(int modelHandle, int status) {
+            Model model = mLoadedModels.get(modelHandle);
+            if (model != null && model.config != null) {
+                android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback.RecognitionEvent event =
+                        new android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback.RecognitionEvent();
+                event.header.model = modelHandle;
+                event.header.type = SoundModelType.GENERIC;
+                event.header.status = status;
+                event.header.captureSession = model.config.base.header.captureHandle;
+                event.header.captureAvailable = true;
+                event.header.audioConfig.channelMask = 16;
+                event.header.audioConfig.format = 1;
+                event.header.audioConfig.sampleRateHz = 16000;
+                event.data = HidlMemoryUtil.byteArrayToHidlMemory(new byte[0]);
+                try {
+                    model.callback.recognitionCallback_2_1(event, 0);
+                } catch (RemoteException e) {
+                    e.printStackTrace();
+                }
+                model.config = null;
+            }
+        }
+
+        public void sendPhraseRecognitionEvent(int modelHandle, int status) {
+            Model model = mLoadedModels.get(modelHandle);
+            if (model != null && model.config != null) {
+                android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback.PhraseRecognitionEvent
+                        event =
+                        new android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback.PhraseRecognitionEvent();
+                event.common.header.model = modelHandle;
+                event.common.header.type = SoundModelType.KEYPHRASE;
+                event.common.header.status = status;
+                event.common.header.captureSession = model.config.base.header.captureHandle;
+                event.common.header.captureAvailable = true;
+                event.common.header.audioConfig.channelMask = 16;
+                event.common.header.audioConfig.format = 1;
+                event.common.header.audioConfig.sampleRateHz = 16000;
+                event.common.data = HidlMemoryUtil.byteArrayToHidlMemory(new byte[0]);
+                if (!model.phraseModel.phrases.isEmpty()) {
+                    PhraseRecognitionExtra extra = new PhraseRecognitionExtra();
+                    extra.id = model.phraseModel.phrases.get(0).id;
+                    extra.confidenceLevel = 100;
+                    extra.recognitionModes = model.phraseModel.phrases.get(0).recognitionModes;
+                    event.phraseExtras.add(extra);
+                }
+                try {
+                    model.callback.phraseRecognitionCallback_2_1(event, 0);
+                } catch (RemoteException e) {
+                    e.printStackTrace();
+                }
+                model.config = null;
+            }
+        }
+
+        @Override
+        public void loadSoundModel_2_1(SoundModel soundModel,
+                android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback callback, int cookie,
+                loadSoundModel_2_1Callback _hidl_cb) {
+            int handle = mHandleCounter++;
+            System.out.printf("loadSoundModel_2_1(soundModel=%s) -> %d%n", soundModel, handle);
+            mLoadedModels.put(handle, new Model(callback, soundModel));
+            _hidl_cb.onValues(0, handle);
+        }
+
+        @Override
+        public void loadPhraseSoundModel_2_1(PhraseSoundModel soundModel,
+                android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback callback, int cookie,
+                loadPhraseSoundModel_2_1Callback _hidl_cb) {
+             int handle = mHandleCounter++;
+            System.out.printf("loadPhraseSoundModel_2_1(soundModel=%s) -> %d%n", soundModel,
+                    handle);
+            mLoadedModels.put(handle, new Model(callback, soundModel));
+            _hidl_cb.onValues(0, handle);
+        }
+
+        @Override
+        public int startRecognition_2_3(int modelHandle,
+                android.hardware.soundtrigger.V2_3.RecognitionConfig config) {
+            System.out.printf("startRecognition_2_3(modelHandle=%d)%n", modelHandle);
+            Model model = mLoadedModels.get(modelHandle);
+            if (model != null) {
+                model.config = config;
+            }
+            return 0;
+        }
+
+        @Override
+        public void getProperties_2_3(getProperties_2_3Callback _hidl_cb) {
+            System.out.println("getProperties_2_3()");
+            android.hardware.soundtrigger.V2_3.Properties properties =
+                    new android.hardware.soundtrigger.V2_3.Properties();
+            properties.base.implementor = "Android";
+            properties.base.description = "Mock STHAL";
+            properties.base.maxSoundModels = 2;
+            properties.base.maxKeyPhrases = 1;
+            properties.base.recognitionModes =
+                    RecognitionMode.VOICE_TRIGGER | RecognitionMode.GENERIC_TRIGGER;
+            _hidl_cb.onValues(0, properties);
+        }
+
+        @Override
+        public void queryParameter(int modelHandle, int modelParam,
+                queryParameterCallback _hidl_cb) {
+            _hidl_cb.onValues(0, new OptionalModelParameterRange());
+        }
+
+        @Override
+        public int getModelState(int modelHandle) {
+            System.out.printf("getModelState(modelHandle=%d)%n", modelHandle);
+            return 0;
+        }
+
+        @Override
+        public int unloadSoundModel(int modelHandle) {
+            System.out.printf("unloadSoundModel(modelHandle=%d)%n", modelHandle);
+            return 0;
+        }
+
+        @Override
+        public int stopRecognition(int modelHandle) {
+            System.out.printf("stopRecognition(modelHandle=%d)%n", modelHandle);
+            Model model = mLoadedModels.get(modelHandle);
+            if (model != null) {
+                model.config = null;
+            }
+            return 0;
+        }
+
+        @Override
+        public void debug(android.os.NativeHandle fd, java.util.ArrayList<String> options) {
+            if (!options.isEmpty()) {
+                switch (options.get(0)) {
+                    case "reboot":
+                        System.out.println("Received a reboot request. Exiting.");
+                        cleanup();
+                        System.exit(1);
+                }
+            }
+        }
+
+        ////////////////////////////////////////////////////////////////////////////////////////////
+        // Everything below is not implemented and not expected to be called.
+
+        @Override
+        public int setParameter(int modelHandle, int modelParam, int value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void getParameter(int modelHandle, int modelParam, getParameterCallback _hidl_cb) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int startRecognition_2_1(int modelHandle, RecognitionConfig config,
+                android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback callback, int cookie) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void getProperties(getPropertiesCallback _hidl_cb) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void loadSoundModel(
+                android.hardware.soundtrigger.V2_0.ISoundTriggerHw.SoundModel soundModel,
+                android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback callback, int cookie,
+                loadSoundModelCallback _hidl_cb) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void loadPhraseSoundModel(
+                android.hardware.soundtrigger.V2_0.ISoundTriggerHw.PhraseSoundModel soundModel,
+                android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback callback, int cookie,
+                loadPhraseSoundModelCallback _hidl_cb) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int startRecognition(int modelHandle,
+                android.hardware.soundtrigger.V2_0.ISoundTriggerHw.RecognitionConfig config,
+                android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback callback, int cookie) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int stopAllRecognitions() {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
diff --git a/soundtrigger/2.3/cli/sthal_cli_2.3 b/soundtrigger/2.3/cli/sthal_cli_2.3
new file mode 100644
index 0000000..78e9f9b
--- /dev/null
+++ b/soundtrigger/2.3/cli/sthal_cli_2.3
@@ -0,0 +1,7 @@
+#!/system/bin/sh
+# Script to start "sthal_cli_2.3" on the device
+#
+base=/system
+export CLASSPATH=$base/framework/sthal_cli_2.3.jar
+exec app_process $base/bin android.hardware.soundtrigger.V2_3.cli.SthalCli "$@"
+
diff --git a/soundtrigger/aidl/Android.bp b/soundtrigger/aidl/Android.bp
new file mode 100644
index 0000000..fcccc27
--- /dev/null
+++ b/soundtrigger/aidl/Android.bp
@@ -0,0 +1,37 @@
+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.soundtrigger3",
+    vendor_available: true,
+    flags: ["-Werror", "-Weverything", ],
+    srcs: [
+        "android/hardware/soundtrigger3/ISoundTriggerHw.aidl",
+        "android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl",
+        "android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl",
+    ],
+    stability: "vintf",
+    imports: [
+        "android.media.soundtrigger.types",
+    ],
+    backend: {
+        cpp: {
+            // prefer NDK backend which can be used anywhere
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHw.aidl b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHw.aidl
new file mode 100644
index 0000000..bbfe7d9
--- /dev/null
+++ b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHw.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.soundtrigger3;
+@VintfStability
+interface ISoundTriggerHw {
+  android.media.soundtrigger.Properties getProperties();
+  void registerGlobalCallback(in android.hardware.soundtrigger3.ISoundTriggerHwGlobalCallback callback);
+  int loadSoundModel(in android.media.soundtrigger.SoundModel soundModel, in android.hardware.soundtrigger3.ISoundTriggerHwCallback callback);
+  int loadPhraseSoundModel(in android.media.soundtrigger.PhraseSoundModel soundModel, in android.hardware.soundtrigger3.ISoundTriggerHwCallback callback);
+  void unloadSoundModel(in int modelHandle);
+  void startRecognition(in int modelHandle, in int deviceHandle, in int ioHandle, in android.media.soundtrigger.RecognitionConfig config);
+  void stopRecognition(in int modelHandle);
+  void forceRecognitionEvent(in int modelHandle);
+  @nullable android.media.soundtrigger.ModelParameterRange queryParameter(in int modelHandle, in android.media.soundtrigger.ModelParameter modelParam);
+  int getParameter(in int modelHandle, in android.media.soundtrigger.ModelParameter modelParam);
+  void setParameter(in int modelHandle, in android.media.soundtrigger.ModelParameter modelParam, in int value);
+}
diff --git a/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl
new file mode 100644
index 0000000..152dfed
--- /dev/null
+++ b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.soundtrigger3;
+@VintfStability
+interface ISoundTriggerHwCallback {
+  void modelUnloaded(in int model);
+  void phraseRecognitionCallback(in int model, in android.media.soundtrigger.PhraseRecognitionEvent event);
+  void recognitionCallback(in int model, in android.media.soundtrigger.RecognitionEvent event);
+}
diff --git a/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl
new file mode 100644
index 0000000..6dfee9f
--- /dev/null
+++ b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.soundtrigger3;
+@VintfStability
+interface ISoundTriggerHwGlobalCallback {
+  void onResourcesAvailable();
+}
diff --git a/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHw.aidl b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHw.aidl
new file mode 100644
index 0000000..2a3fc64
--- /dev/null
+++ b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHw.aidl
@@ -0,0 +1,269 @@
+/*
+ * 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.soundtrigger3;
+
+import android.hardware.soundtrigger3.ISoundTriggerHwCallback;
+import android.hardware.soundtrigger3.ISoundTriggerHwGlobalCallback;
+
+import android.media.soundtrigger.PhraseSoundModel;
+import android.media.soundtrigger.Properties;
+import android.media.soundtrigger.RecognitionConfig;
+import android.media.soundtrigger.SoundModel;
+import android.media.soundtrigger.ModelParameter;
+import android.media.soundtrigger.ModelParameterRange;
+import android.media.soundtrigger.Properties;
+import android.media.soundtrigger.RecognitionConfig;
+
+/**
+ * SoundTrigger HAL interface. Used for hardware recognition of hotwords
+ * and other sounds.
+ *
+ * Basic usage:
+ * ============
+ * ISoundTriggerHw supports the ability to have one of more  detection sessions running at a given
+ * time, and listening to acoustic events. The basic flow of setting up such a session is:
+ * - Load a model using loadSoundModel() or loadPhraseSoundModel(). The provided model object would
+ *   indicate the (implementation-specific) detection algorithm (engine) to use, as well as any
+ *   parameters applicable for this agorithm. Upon success, those methods would return a handle
+ *   which will be used to reference this model in subsequent calls.
+ * - Once the model had been successfully loaded, detection can begin by calling startRecognition().
+ * - Recognition will continue running in the background until one of the following events occurs:
+ *   - stopRecognition() has been called on this model.
+ *   - A detection has occurred.
+ *   - Detection was aborted, typically for resource constraints, for example, when a higher-
+ *     priority use-case has been initiated.
+ * - In the latter two cases, a recognition event will be sent via a the callback interface that was
+ *   registered by the client upon loading. In either case, after any of these events occur, the
+ *   detection becomes inactive and no more recognition callbacks are allowed.
+ * - The same model maybe started again at a later time, and this process may repeat as many times
+ *   as needed.
+ * - Finally, an inactive model that is no longer needed may be unloaded via unloadModel().
+ *
+ * Important notes about the threading model:
+ * ==========================================
+ * Both this interface and the corresponding callback interface use a synchronous calling
+ * convention. This model comes with some advantages, but also with some risks of deadlocks if the
+ * implementation does not handle this correctly. Please consider the following:
+ * - After stopRecognition() returns, no more recognition events for that model may be sent. This
+ *   implies that any queues holding such events must be flushed before the call returns and that
+ *   may imply that callback from the HAL to the client are done while stopRecognition() is blocked.
+ *   This is OK, and supported by the framework.
+ * - Similarly, the same relationship applies between unloadModel() and subsequent callbacks to
+ *   modelUnloaded().
+ * - Other than these two cases, calls into the HAL *MAY NOT* block on callbacks from the HAL, or
+ *   else deadlock conditions may result, which may be handled by rebooting of the HAL process and
+ *   cause service outages.
+ *
+ * Due to the asynchronous nature of recognition events and preemptive model unloading, the HAL must
+ * correctly handle requests that would have been valid before an event has been delivered, but
+ * became moot as result of the event. Namely:
+ * - stopRecognition() may be called on a model that has already delivered an event and became
+ *   inactive as a result. The HAL must return a successful return code in this case.
+ * - Furthermore, if a model is preemptively unloaded after it triggers (typically, this would
+ *   happen when it is first aborted and immediately preemptively unloaded), stopRecognition() may
+ *   be called on it. The HAL must return successfully in this case.
+ * - startRecognition() may be called on a model that has been preemptively unloaded. In this case,
+ *   the HAL must signal a ServiceSpecificException(RESOURCE_CONTENTION) to indicate that the
+ *   operation is temporarily unsuccessful.
+ * - unloadSoundModel() may be called on a model that has been preemptively unloaded. The HAL must
+ *   return a successful return code in this case. This also implies that model handles should
+ *   generally not be reused until explicitly unloaded. To avoid the rare possibility of running out
+ *   of handles, the framework may call unloadModel() on models that have been preemptively unloaded
+ *   by the HAL.
+ *
+ * Important notes about resource constraints and concurrency
+ * =========================================================
+ * Up until this version, the framework would enforce concurrency constraints expressed by the
+ * Properties presented by the soundtrigger instance. These include constraints on the maximum
+ * amount of models that can be loaded at the same time and on running recognition while capturing
+ * from the microphone.
+ * This version changes the approach for how these constraints are modeled, both offering the HAL
+ * implementation more flexibility and simplifying the framework's job in enforcing these
+ * limitations. Note that there is no change for how the framework behaves with earlier versions,
+ * everything described below only applies to this version and onward.
+ * The way this is achieved is as following:
+ * - The framework will no longer enforce constraints on concurrent loading of models, as expressed
+ *   in the Properties.maxSoundModels field (this property is merely a hint at this point and may be
+ *   deprecated in the future), or any other implicit constraints.
+ * - The framework will no longer enforce constraints on concurrency of audio recording and
+ *   soundtrigger operation, as expressed in the Properties.concurrentCapture field (this property
+ *   is merely a hint at this point and may be deprecated in the future).
+ * - The HAL implementation is free to reject loading of any model at any time by having the
+ *   respective load*() method signal a ServiceSpecificException(RESOURCE_CONTENTION).
+ * - The HAL implementation is free to reject starting of any model at any time by having the
+ *   respective start*() method signal a ServiceSpecificException(RESOURCE_CONTENTION).
+ * - The HAL implementation is free to preemptively stop a previously started model at its own
+ *   discretion (for example, if a higher priority use-case which cannot coexist with detection
+ *   has been requested). The HAL must notify the framework of the preemption by sending a
+ *   recognition event with an `ABORTED` status. The implementation must NOT attempt to restart the
+ *   recognition automatically when conditions change.
+ * - The HAL implementation is free to preemptively unload a previously loaded model at its own
+ *   discretion (for example, if a higher-priority model is being loaded and the two cannot
+ *   coexist). When doing so, it must first abort the detection if active (as per above) and then
+ *   notify the framework of the unload using the modelUnloaded() callback.
+ * - When conditions change, such that a model that couldn't previously load or start or that had
+ *   previously been preemptively stopped or unloaded, the HAL must notify the framework via the
+ *   newly added onResourcesAvailable() callback. This callback is not a guarantee that any
+ *   operation would now succeed, but merely a hint that retrying something that had previously
+ *   failed, now MAY succeed. Until this callback is invoked, the client may assume that any
+ *   operation that had previously failed or aborted would still fail if retried, so the
+ *   implementation should not forget to deliver it.
+ *   There are no guarantees regarding how the framework may respond to this event and the order in
+ *   which it may choose to reload/restart its models. Typically, as result of this event the
+ *   framework will make a single attempt per model to bring this model to its desired state
+ *   (loaded, started).
+ */
+@VintfStability
+interface ISoundTriggerHw {
+    /**
+     * Retrieve implementation properties.
+     *
+     * @return A Properties structure containing implementation description and capabilities.
+     */
+    Properties getProperties();
+
+    /**
+     * This will get called at most once per every attachment to the service.
+     *
+     * All events not tied to a specific model should go through this callback.
+     *
+     * @param callback An interface to receive global event callbacks.
+     */
+    void registerGlobalCallback(in ISoundTriggerHwGlobalCallback callback);
+
+    /**
+     * Load a sound model. Once loaded, recognition of this model can be started and stopped.
+     *
+     * @param soundModel A SoundModel structure describing the sound model to load.
+     * @param callback The callback interface on which the recognitionCallback()
+     *     method will be called upon completion and modelUnloaded() upon preemptive unload.
+     * @return A unique handle assigned by the HAL for use by the client when controlling
+     *     activity for this sound model.
+     * @throws ServiceSpecificException(RESOURCE_CONTENTION) if the model cannot be loaded due
+     *     to resource constraints. This is typically a temporary condition and the client may
+     *     retry after the onResourcesAvailable() global callback is invoked.
+     */
+    int loadSoundModel(in SoundModel soundModel, in ISoundTriggerHwCallback callback);
+
+    /**
+     * Load a key phrase sound model. Once loaded, recognition of this model can be started and
+     * stopped.
+     *
+     * @param soundModel A PhraseSoundModel structure describing the sound model to load.
+     * @param callback The callback interface on which the phraseRecognitionCallback() method will
+     *     be called upon completion and modelUnloaded() upon preempted unload.
+     * @return A unique handle assigned by the HAL for use by the framework when controlling
+     *     activity for this sound model.
+     * @throws ServiceSpecificException(RESOURCE_CONTENTION) if the model cannot be loaded due
+     *     to resource constraints. This is typically a temporary condition and the client may
+     *     retry after the onResourcesAvailable() global callback is invoked.
+     */
+    int loadPhraseSoundModel(in PhraseSoundModel soundModel, in ISoundTriggerHwCallback callback);
+
+    /**
+     * Unload a sound model. A sound model may be unloaded to free up resources and make room for a
+     * new one to overcome implementation limitations.
+     * This call is idempotent, to avoid any race conditions.
+     *
+     * @param modelHandle the handle of the sound model to unload.
+     */
+    void unloadSoundModel(in int modelHandle);
+
+    /**
+     * Start recognition on a given model.
+     * This must be called on a model that is in the stopped state.
+     * The state of this model becomes active and will remain so until explicitly stopped, or a
+     * recognition event had been delivered to the client.
+     *
+     * @param modelHandle the handle of the sound model to use for recognition
+     * @param deviceHandle The handle of the audio device to be used for recognition, as declared by
+     *     the audio subsystem.
+     * @param ioHandle A handle assigned by the framework, which will later be used to retrieve
+     *     an audio stream associated with this recognition session.
+     * @param config A RecognitionConfig structure containing attributes of the recognition to
+     *     perform.
+      * @throws ServiceSpecificException(RESOURCE_CONTENTION) if the model cannot be started due
+     *     to resource constraints. This is typically a temporary condition and the client may
+     *     retry after the onResourcesAvailable() global callback is invoked.
+    */
+    void startRecognition(in int modelHandle, in int deviceHandle,
+                          in int ioHandle, in RecognitionConfig config);
+
+    /**
+     * Stop recognition on a given model.
+     * This call is idempotent, to avoid any race conditions.
+     *
+     * @param modelHandle The handle of the sound model to use for recognition
+     */
+    void stopRecognition(in int modelHandle);
+
+    /**
+     * Request a recognition event to be generated.
+     * The model must be in the started state and will remain started after the event is sent.
+     * The model state is returned asynchronously as a RecognitionEvent via the callback that was
+     * registered upon loading. That event must have a RecognitionStatus.FORCED status.
+     *
+     * @param modelHandle The handle of the sound model whose state is being
+     *     queried.
+     */
+    void forceRecognitionEvent(in int modelHandle);
+
+    /**
+     * Get supported parameter attributes with respect to the provided model handle.
+     * Model parameters are used to query/control model-specific detection behavior during a
+     * detection session.
+     * Along with determining the valid range, this API is also used to determine if a given
+     * parameter ID is supported at all by the modelHandle for use with getParameter() and
+     * setParameter() APIs.
+     *
+     * @param modelHandle The sound model handle indicating which model to query.
+     * @param modelParam Parameter to set which will be validated against the ModelParameter type.
+     * @return This structure indicates supported attributes of the parameter for the given model
+     *      handle. If the parameter is not supported, null is returned.
+     */
+    @nullable ModelParameterRange queryParameter(in int modelHandle, in ModelParameter modelParam);
+
+    /**
+     * Get a model specific parameter.
+     * If the value has not been set, a default value is returned. See ModelParameter for parameter
+     * default values.
+     * The caller must check if the handle supports the parameter via the queryParameter API prior
+     * to calling this method.
+     *
+     * @param modelHandle The sound model associated with given modelParam
+     * @param modelParam Parameter to set which will be validated against the ModelParameter type.
+     *     Not putting ModelParameter type directly in the definition and validating internally
+     *     allows for forward compatibility.
+     * @return Value set to the requested parameter.
+     */
+    int getParameter(in int modelHandle, in ModelParameter modelParam);
+
+    /**
+     * Set a model specific parameter with the given value.
+     * This parameter will keep its value for the duration the model is loaded regardless of
+     * starting and stopping recognition. Once the model is unloaded, the value will be lost.
+     * The caller must check if the handle supports the parameter via the queryParameter API prior
+     * to calling this method.
+     *
+     * @param modelHandle The sound model handle indicating which model to modify parameters
+     * @param modelParam Parameter to set which will be validated against the ModelParameter type.
+     *     Not putting ModelParameter type directly in the definition and validating internally
+     *     allows for forward compatibility.
+     * @param value The value to set for the given model parameter.
+     */
+    void setParameter(in int modelHandle, in ModelParameter modelParam, in int value);
+}
diff --git a/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl
new file mode 100644
index 0000000..049ca65
--- /dev/null
+++ b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl
@@ -0,0 +1,59 @@
+/*
+ * 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.soundtrigger3;
+
+import android.media.soundtrigger.PhraseRecognitionEvent;
+import android.media.soundtrigger.RecognitionEvent;
+
+/**
+ * SoundTrigger HAL per-model Callback interface.
+ */
+@VintfStability
+interface ISoundTriggerHwCallback {
+    /**
+     * Callback method called by the HAL when a model has been unloaded at the HAL implementation's
+     * discretion.
+     * This event may only be delivered when the model state is 'stopped'.
+     * This event is NOT sent as part of an unload sequence initiated by the client.
+     *
+     * @param model The model handle.
+     */
+    void modelUnloaded(in int model);
+
+    /**
+     * Callback method called by the HAL when the sound recognition triggers for a key phrase sound
+     * model.
+     * This event may only be delivered when the model state is 'started'.
+     * Unless the status of the event is RecognitionStatus.FORCED, this event indicates that the
+     * state of this model has become 'stopped'.
+     *
+     * @param event A RecognitionEvent structure containing detailed results of the recognition
+     *     triggered
+     */
+    void phraseRecognitionCallback(in int model, in PhraseRecognitionEvent event);
+
+    /**
+     * Callback method called by the HAL when the sound recognition triggers.
+     * This event may only be delivered when the model state is 'started'.
+     * Unless the status of the event is RecognitionStatus.FORCED, this event indicates that the
+     * state of this model has become 'stopped'.
+     *
+     * @param event A RecognitionEvent structure containing detailed results of the recognition
+     *     triggered
+     */
+    void recognitionCallback(in int model, in RecognitionEvent event);
+}
diff --git a/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl
new file mode 100644
index 0000000..d6d8630
--- /dev/null
+++ b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.soundtrigger3;
+
+/**
+ * SoundTrigger HAL callback interface for events not associated with a particular model.
+ */
+@VintfStability
+interface ISoundTriggerHwGlobalCallback {
+    /**
+     * Callback method called by the HAL whenever internal conditions have been made available, such
+     * that a call that would previously have failed with an -EBUSY status may now succeed.
+     * There is no guarantee that any call would succeed following this event. It is merely a hint
+     * to the client that it may retry.
+     * Conversely, any call that have failed previously with a
+     * ServiceSpecificException(RESOURCE_CONTENTION) is guaranteed to fail again if retried, until
+     * this callback is delivered.
+     */
+    void onResourcesAvailable();
+}
diff --git a/soundtrigger/aidl/cli/Android.bp b/soundtrigger/aidl/cli/Android.bp
new file mode 100644
index 0000000..e8999ff
--- /dev/null
+++ b/soundtrigger/aidl/cli/Android.bp
@@ -0,0 +1,17 @@
+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"],
+}
+
+java_binary {
+    name: "sthal_cli_3",
+    wrapper: "sthal_cli_3",
+    srcs: ["java/**/*.java"],
+    static_libs: [
+        "android.hardware.soundtrigger3-V1-java",
+    ],
+}
diff --git a/soundtrigger/aidl/cli/OWNERS b/soundtrigger/aidl/cli/OWNERS
new file mode 100644
index 0000000..9f87c4c
--- /dev/null
+++ b/soundtrigger/aidl/cli/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/media/aidl/android/media/soundtrigger_middleware/OWNERS
diff --git a/soundtrigger/aidl/cli/java/android/hardware/soundtrigger3/cli/SthalCli.java b/soundtrigger/aidl/cli/java/android/hardware/soundtrigger3/cli/SthalCli.java
new file mode 100644
index 0000000..0fd1dda
--- /dev/null
+++ b/soundtrigger/aidl/cli/java/android/hardware/soundtrigger3/cli/SthalCli.java
@@ -0,0 +1,361 @@
+/*
+ * 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.soundtrigger3.cli;
+
+import android.annotation.NonNull;
+import android.hardware.soundtrigger3.ISoundTriggerHw;
+import android.hardware.soundtrigger3.ISoundTriggerHwCallback;
+import android.hardware.soundtrigger3.ISoundTriggerHwGlobalCallback;
+import android.media.audio.common.AudioChannelLayout;
+import android.media.audio.common.AudioConfig;
+import android.media.audio.common.AudioConfigBase;
+import android.media.audio.common.AudioFormatDescription;
+import android.media.audio.common.AudioFormatType;
+import android.media.audio.common.PcmType;
+import android.media.soundtrigger.ConfidenceLevel;
+import android.media.soundtrigger.ModelParameterRange;
+import android.media.soundtrigger.PhraseRecognitionEvent;
+import android.media.soundtrigger.PhraseRecognitionExtra;
+import android.media.soundtrigger.PhraseSoundModel;
+import android.media.soundtrigger.Properties;
+import android.media.soundtrigger.RecognitionConfig;
+import android.media.soundtrigger.RecognitionEvent;
+import android.media.soundtrigger.RecognitionMode;
+import android.media.soundtrigger.SoundModel;
+import android.media.soundtrigger.SoundModelType;
+import android.os.HwBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import java.util.Scanner;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * This is a quick-and-dirty sound trigger HAL console mock.
+ *
+ * It would only work on userdebug builds.
+ *
+ * When this app is started, it will initially:
+ * - Register a ISoundTriggerHw HAL with an instance name "mock".
+ * - Set a sysprop that tells SoundTriggerMiddlewareService to try to connect to the mock instance
+ * rather than the default one.
+ * - Reboot the real (default) HAL.
+ *
+ * In response to that, SoundTriggerMiddlewareService is going to connect to the mock HAL and resume
+ * normal operation.
+ *
+ * Our mock HAL will print to stdout every call it receives as well as expose a basic set of
+ * operations for sending event callbacks to the client. This allows us to simulate the frameworks
+ * behavior in response to different HAL behaviors.
+ */
+public class SthalCli {
+    private static SoundTriggerImpl mService;
+    private static final Scanner scanner = new Scanner(System.in);
+
+    public static void main(String[] args) {
+        try {
+            printUsage();
+
+            System.out.println("Registering mock STHAL");
+            mService = new SoundTriggerImpl();
+            // This allows us to register the service, even if it is not declared in the manifest.
+            mService.forceDowngradeToSystemStability();
+            ServiceManager.addService(ISoundTriggerHw.class.getCanonicalName() + "/mock", mService);
+
+            System.out.println("Rebooting STHAL");
+            SystemProperties.set("debug.soundtrigger_middleware.use_mock_hal", "3");
+            SystemProperties.set("sys.audio.restart.hal", "1");
+
+            while (processCommand()) ;
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            cleanup();
+        }
+    }
+
+    private static void cleanup() {
+        System.out.println("Cleaning up.");
+        SystemProperties.set("debug.soundtrigger_middleware.use_mock_hal", null);
+        HwBinder.setTrebleTestingOverride(false);
+    }
+
+    private static boolean processCommand() {
+        String line = scanner.nextLine();
+        String[] tokens = line.split("\\s+");
+        if (tokens.length < 1) {
+            return false;
+        }
+        switch (tokens[0]) {
+            case "q":
+                return false;
+
+            case "a":
+                mService.sendOnResourcesAvailable();
+                return true;
+
+            case "u":
+                mService.sendModelUnloaded(Integer.parseInt(tokens[1]));
+                return true;
+
+            case "r":
+                mService.sendRecognitionEvent(Integer.parseInt(tokens[1]),
+                        Integer.parseInt(tokens[2]));
+                return true;
+
+            case "p":
+                mService.sendPhraseRecognitionEvent(Integer.parseInt(tokens[1]),
+                        Integer.parseInt(tokens[2]));
+                return true;
+
+            case "d":
+                mService.dumpModels();
+                return true;
+
+            default:
+                printUsage();
+                return true;
+        }
+    }
+
+    private static void printUsage() {
+        System.out.print(
+                "Sound Trigger HAL v3 mock\n"
+                + "Available commands:\n"
+                + "h - help\n"
+                + "q - quit\n"
+                + "a - send onResourcesAvailable event\n"
+                + "u <model> - send modelUnloaded event\n"
+                + "r <model> <status> - send recognitionEvent\n"
+                + "p <model> <status> - send phraseRecognitionEvent\n"
+                + "d - dump models\n");
+    }
+
+    private static class SoundTriggerImpl extends ISoundTriggerHw.Stub {
+        static class Model {
+            final ISoundTriggerHwCallback callback;
+            final SoundModel model;
+            final PhraseSoundModel phraseModel;
+            public RecognitionConfig config = null;
+
+            Model(ISoundTriggerHwCallback callback, SoundModel model) {
+                this.callback = callback;
+                this.model = model;
+                this.phraseModel = null;
+            }
+
+            Model(ISoundTriggerHwCallback callback, PhraseSoundModel model) {
+                this.callback = callback;
+                this.model = null;
+                this.phraseModel = model;
+            }
+        }
+
+        private ISoundTriggerHwGlobalCallback mGlobalCallback;
+        private final ConcurrentMap<Integer, Model> mLoadedModels = new ConcurrentHashMap<>();
+        private int mHandleCounter = 1;
+
+        public void dumpModels() {
+            mLoadedModels.forEach((handle, model) -> {
+                System.out.println("+++ Model " + handle);
+                System.out.println("    config = " + model.config);
+                RecognitionConfig recognitionConfig = model.config;
+                if (recognitionConfig != null) {
+                    System.out.println("    ACTIVE recognitionConfig = " + recognitionConfig);
+                } else {
+                    System.out.println("    INACTIVE");
+                }
+            });
+        }
+
+        public void sendOnResourcesAvailable() {
+            if (mGlobalCallback != null) {
+                try {
+                    mGlobalCallback.onResourcesAvailable();
+                } catch (RemoteException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        public void sendRecognitionEvent(int modelHandle, int status) {
+            Model model = mLoadedModels.get(modelHandle);
+            if (model != null && model.config != null) {
+                RecognitionEvent event = new RecognitionEvent();
+                event.type = SoundModelType.GENERIC;
+                event.status = status;
+                event.captureAvailable = true;
+                event.audioConfig = createConfig();
+                try {
+                    model.callback.recognitionCallback(modelHandle, event);
+                } catch (RemoteException e) {
+                    e.printStackTrace();
+                }
+                model.config = null;
+            }
+        }
+
+        public void sendPhraseRecognitionEvent(int modelHandle, int status) {
+            Model model = mLoadedModels.get(modelHandle);
+            if (model != null && model.config != null) {
+                PhraseRecognitionEvent event = new PhraseRecognitionEvent();
+                event.common = new RecognitionEvent();
+                event.common.type = SoundModelType.KEYPHRASE;
+                event.common.status = status;
+                event.common.captureAvailable = true;
+                event.common.audioConfig = createConfig();
+                if (model.phraseModel.phrases.length > 0) {
+                    PhraseRecognitionExtra extra = new PhraseRecognitionExtra();
+                    extra.id = model.phraseModel.phrases[0].id;
+                    extra.confidenceLevel = 100;
+                    extra.recognitionModes = model.phraseModel.phrases[0].recognitionModes;
+                    extra.levels = new ConfidenceLevel[0];
+                    event.phraseExtras = new PhraseRecognitionExtra[]{extra};
+                } else {
+                    event.phraseExtras = new PhraseRecognitionExtra[0];
+                }
+                try {
+                    model.callback.phraseRecognitionCallback(modelHandle, event);
+                } catch (RemoteException e) {
+                    e.printStackTrace();
+                }
+                model.config = null;
+            }
+        }
+
+        public void sendModelUnloaded(int modelHandle) {
+            Model model = mLoadedModels.remove(modelHandle);
+            if (model != null) {
+                try {
+                    model.callback.modelUnloaded(modelHandle);
+                } catch (RemoteException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        @Override
+        public void registerGlobalCallback(ISoundTriggerHwGlobalCallback callback) {
+            System.out.println("registerGlobalCallback()");
+            mGlobalCallback = callback;
+        }
+
+        @Override
+        public int loadSoundModel(SoundModel soundModel, ISoundTriggerHwCallback callback) {
+            int handle = mHandleCounter++;
+            System.out.printf("loadSoundModel(soundModel=%s) -> %d%n", soundModel, handle);
+            mLoadedModels.put(handle, new Model(callback, soundModel));
+            return handle;
+        }
+
+        @Override
+        public int loadPhraseSoundModel(PhraseSoundModel soundModel,
+                ISoundTriggerHwCallback callback) {
+            int handle = mHandleCounter++;
+            System.out.printf("loadPhraseSoundModel(soundModel=%s) -> %d%n", soundModel, handle);
+            mLoadedModels.put(handle, new Model(callback, soundModel));
+            return handle;
+        }
+
+        @Override
+        public void startRecognition(int modelHandle, int deviceHandle, int ioHandle,
+                RecognitionConfig config) {
+            System.out.printf("startRecognition(modelHandle=%d, deviceHandle=%d, ioHandle=%d)%n",
+                    modelHandle, deviceHandle, ioHandle);
+            Model model = mLoadedModels.get(modelHandle);
+            if (model != null) {
+                model.config = config;
+            }
+        }
+
+        @Override
+        public Properties getProperties() {
+            System.out.println("getProperties()");
+            Properties properties = new Properties();
+            properties.implementor = "Android";
+            properties.description = "Mock STHAL";
+            properties.maxSoundModels = 2;
+            properties.maxKeyPhrases = 1;
+            properties.recognitionModes =
+                    RecognitionMode.VOICE_TRIGGER | RecognitionMode.GENERIC_TRIGGER;
+            return properties;
+        }
+
+        @Override
+        public ModelParameterRange queryParameter(int modelHandle, int modelParam) {
+            System.out.printf("queryParameter(modelHandle=%d, modelParam=%d)%n", modelHandle,
+                    modelParam);
+            return null;
+        }
+
+        @Override
+        public void forceRecognitionEvent(int modelHandle) {
+            System.out.printf("getModelState(modelHandle=%d)%n", modelHandle);
+        }
+
+        @Override
+        public void unloadSoundModel(int modelHandle) {
+            System.out.printf("unloadSoundModel(modelHandle=%d)%n", modelHandle);
+        }
+
+        @Override
+        public void stopRecognition(int modelHandle) {
+            System.out.printf("stopRecognition(modelHandle=%d)%n", modelHandle);
+            Model model = mLoadedModels.get(modelHandle);
+            if (model != null) {
+                model.config = null;
+            }
+        }
+
+        @Override
+        public int handleShellCommand(@NonNull ParcelFileDescriptor in,
+                @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
+                @NonNull String[] args) {
+            if (args.length > 0) {
+                switch (args[0]) {
+                    case "reboot":
+                        System.out.println("Received a reboot request. Exiting.");
+                        cleanup();
+                        System.exit(1);
+                }
+            }
+            return 0;
+        }
+
+        @Override
+        public void setParameter(int modelHandle, int modelParam, int value) {
+            throw new IllegalArgumentException();
+        }
+
+        @Override
+        public int getParameter(int modelHandle, int modelParam) {
+            throw new IllegalArgumentException();
+        }
+
+        private static AudioConfig createConfig() {
+            AudioConfig config = new AudioConfig();
+            config.base = new AudioConfigBase();
+            config.base.channelMask = AudioChannelLayout.layoutMask(AudioChannelLayout.LAYOUT_MONO);
+            config.base.format = new AudioFormatDescription();
+            config.base.format.type = AudioFormatType.PCM;
+            config.base.format.pcm = PcmType.INT_16_BIT;
+            config.base.sampleRate = 16000;
+            return config;
+        }
+    }
+}
diff --git a/soundtrigger/aidl/cli/sthal_cli_3 b/soundtrigger/aidl/cli/sthal_cli_3
new file mode 100644
index 0000000..f157c50
--- /dev/null
+++ b/soundtrigger/aidl/cli/sthal_cli_3
@@ -0,0 +1,6 @@
+#!/system/bin/sh
+# Script to start "sthal_cli_3" on the device
+#
+base=/system
+export CLASSPATH=$base/framework/sthal_cli_3.jar
+exec app_process $base/bin android.hardware.soundtrigger3.cli.SthalCli "$@"
diff --git a/tv/tuner/1.0/default/Dvr.cpp b/tv/tuner/1.0/default/Dvr.cpp
index c3edac9..40879f2 100644
--- a/tv/tuner/1.0/default/Dvr.cpp
+++ b/tv/tuner/1.0/default/Dvr.cpp
@@ -37,7 +37,10 @@
     mDemux = demux;
 }
 
-Dvr::~Dvr() {}
+Dvr::~Dvr() {
+    // make sure thread has joined
+    close();
+}
 
 Return<void> Dvr::getQueueDesc(getQueueDesc_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
@@ -112,8 +115,7 @@
     }
 
     if (mType == DvrType::PLAYBACK) {
-        pthread_create(&mDvrThread, NULL, __threadLoopPlayback, this);
-        pthread_setname_np(mDvrThread, "playback_waiting_loop");
+        mDvrThread = std::thread(&Dvr::playbackThreadLoop, this);
     } else if (mType == DvrType::RECORD) {
         mRecordStatus = RecordStatus::DATA_READY;
         mDemux->setIsRecording(mType == DvrType::RECORD);
@@ -128,10 +130,11 @@
     ALOGV("%s", __FUNCTION__);
 
     mDvrThreadRunning = false;
-
-    lock_guard<mutex> lock(mDvrThreadLock);
-
-    mIsRecordStarted = false;
+    if (mDvrThread.joinable()) {
+        mDvrThread.join();
+    }
+    // thread should always be joinable if it is running,
+    // so it should be safe to assume recording stopped.
     mDemux->setIsRecording(false);
 
     return Result::SUCCESS;
@@ -147,7 +150,7 @@
 
 Return<Result> Dvr::close() {
     ALOGV("%s", __FUNCTION__);
-
+    stop();
     return Result::SUCCESS;
 }
 
@@ -174,15 +177,8 @@
     return mDvrEventFlag;
 }
 
-void* Dvr::__threadLoopPlayback(void* user) {
-    Dvr* const self = static_cast<Dvr*>(user);
-    self->playbackThreadLoop();
-    return 0;
-}
-
 void Dvr::playbackThreadLoop() {
     ALOGD("[Dvr] playback threadLoop start.");
-    lock_guard<mutex> lock(mDvrThreadLock);
     mDvrThreadRunning = true;
 
     while (mDvrThreadRunning) {
diff --git a/tv/tuner/1.0/default/Dvr.h b/tv/tuner/1.0/default/Dvr.h
index 3069586..fd7fba2 100644
--- a/tv/tuner/1.0/default/Dvr.h
+++ b/tv/tuner/1.0/default/Dvr.h
@@ -20,7 +20,9 @@
 #include <android/hardware/tv/tuner/1.0/IDvr.h>
 #include <fmq/MessageQueue.h>
 #include <math.h>
+#include <atomic>
 #include <set>
+#include <thread>
 #include "Demux.h"
 #include "Frontend.h"
 #include "Tuner.h"
@@ -119,10 +121,7 @@
      * Each filter handler handles the data filtering/output writing/filterEvent updating.
      */
     void startTpidFilter(vector<uint8_t> data);
-    static void* __threadLoopPlayback(void* user);
-    static void* __threadLoopRecord(void* user);
     void playbackThreadLoop();
-    void recordThreadLoop();
 
     unique_ptr<DvrMQ> mDvrMQ;
     EventFlag* mDvrEventFlag;
@@ -133,7 +132,7 @@
     DvrSettings mDvrSettings;
 
     // Thread handlers
-    pthread_t mDvrThread;
+    std::thread mDvrThread;
 
     // FMQ status local records
     PlaybackStatus mPlaybackStatus;
@@ -141,7 +140,7 @@
     /**
      * If a specific filter's writing loop is still running
      */
-    bool mDvrThreadRunning;
+    std::atomic<bool> mDvrThreadRunning;
     bool mKeepFetchingDataFromFrontend;
     /**
      * Lock to protect writes to the FMQs
@@ -152,13 +151,8 @@
      */
     std::mutex mPlaybackStatusLock;
     std::mutex mRecordStatusLock;
-    std::mutex mDvrThreadLock;
 
     const bool DEBUG_DVR = false;
-
-    // Booleans to check if recording is running.
-    // Recording is ready when both of the following are set to true.
-    bool mIsRecordStarted = false;
 };
 
 }  // namespace implementation
@@ -168,4 +162,4 @@
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_TV_TUNER_V1_0_DVR_H_
\ No newline at end of file
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_0_DVR_H_
diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp
index 6561c92..6e82b8b 100644
--- a/tv/tuner/1.0/default/Frontend.cpp
+++ b/tv/tuner/1.0/default/Frontend.cpp
@@ -104,7 +104,7 @@
 
     uint32_t frequency = settings.dvbt().frequency;
     if (type == FrontendScanType::SCAN_BLIND) {
-        frequency += 100;
+        frequency += 100 * 1000;
     }
     msg.frequencies({frequency});
     mCallback->onScanMessage(FrontendScanMessageType::FREQUENCY, msg);
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
index c4f610e..2157bdf 100644
--- a/tv/tuner/1.0/default/Tuner.cpp
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -175,8 +175,8 @@
     // assign randomly selected values for testing.
     info = {
             .type = mFrontends[frontendId]->getFrontendType(),
-            .minFrequency = 139,
-            .maxFrequency = 1139,
+            .minFrequency = 139000000,
+            .maxFrequency = 1139000000,
             .minSymbolRate = 45,
             .maxSymbolRate = 1145,
             .acquireRange = 30,
diff --git a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc
index 5d5b943..2b1b379 100644
--- a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc
+++ b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc
@@ -4,3 +4,4 @@
     group mediadrm drmrpc
     ioprio rt 4
     task_profiles ProcessCapacityHigh
+    onrestart restart media.tuner
diff --git a/tv/tuner/1.0/vts/functional/DvrTests.cpp b/tv/tuner/1.0/vts/functional/DvrTests.cpp
index 599abfb..83f9858 100644
--- a/tv/tuner/1.0/vts/functional/DvrTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DvrTests.cpp
@@ -124,11 +124,9 @@
     while (mDataOutputBuffer.empty()) {
         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
             EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
-            stopRecordThread();
             return;
         }
     }
-    stopRecordThread();
     ALOGW("[vts] record pass and stop");
 }
 
@@ -193,9 +191,10 @@
 bool DvrCallback::readRecordFMQ() {
     android::Mutex::Autolock autoLock(mMsgLock);
     bool result = false;
+    int readSize = mRecordMQ->availableToRead();
     mDataOutputBuffer.clear();
-    mDataOutputBuffer.resize(mRecordMQ->availableToRead());
-    result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead());
+    mDataOutputBuffer.resize(readSize);
+    result = mRecordMQ->read(mDataOutputBuffer.data(), readSize);
     EXPECT_TRUE(result) << "can't read from Record MQ";
     mMsgCondition.signal();
     return result;
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.cpp b/tv/tuner/1.0/vts/functional/FilterTests.cpp
index f470245..a7792f5 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FilterTests.cpp
@@ -16,7 +16,7 @@
 
 #include "FilterTests.h"
 
-void FilterCallback::startFilterEventThread(DemuxFilterEvent event) {
+void FilterCallback::startFilterEventThread(DemuxFilterEvent& event) {
     struct FilterThreadArgs* threadArgs =
             (struct FilterThreadArgs*)malloc(sizeof(struct FilterThreadArgs));
     threadArgs->user = this;
@@ -69,9 +69,8 @@
     // end thread
 }
 
-bool FilterCallback::readFilterEventData() {
+bool FilterCallback::readFilterEventData(const DemuxFilterEvent& filterEvent) {
     bool result = false;
-    DemuxFilterEvent filterEvent = mFilterEvent;
     ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
     // todo separate filter handlers
     for (auto event : filterEvent.events) {
@@ -107,7 +106,7 @@
     return result;
 }
 
-bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
+bool FilterCallback::dumpAvData(DemuxFilterMediaEvent& event) {
     uint32_t length = event.dataLength;
     uint64_t dataId = event.avDataId;
     // read data from buffer pointed by a handle
@@ -127,7 +126,7 @@
     return true;
 }
 
-bool FilterCallback::readRecordData(DemuxFilterTsRecordEvent event) {
+bool FilterCallback::readRecordData(DemuxFilterTsRecordEvent& event) {
     ALOGD("[vts] got DemuxFilterTsRecordEvent with pid=%d.", event.pid.tPid());
     return true;
 }
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.h b/tv/tuner/1.0/vts/functional/FilterTests.h
index 7bc4832..d37b9e1 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.h
+++ b/tv/tuner/1.0/vts/functional/FilterTests.h
@@ -77,8 +77,7 @@
         android::Mutex::Autolock autoLock(mMsgLock);
         // Temprarily we treat the first coming back filter data on the matching pid a success
         // once all of the MQ are cleared, means we got all the expected output
-        mFilterEvent = filterEvent;
-        readFilterEventData();
+        readFilterEventData(filterEvent);
         mPidFilterOutputCount++;
         // mFilterIdToMQ.erase(filterEvent.filterId);
 
@@ -96,15 +95,15 @@
 
     void testFilterDataOutput();
 
-    void startFilterEventThread(DemuxFilterEvent event);
+    void startFilterEventThread(DemuxFilterEvent& event);
     static void* __threadLoopFilter(void* threadArgs);
     void filterThreadLoop(DemuxFilterEvent& event);
 
     void updateFilterMQ(MQDesc& filterMQDescriptor);
     void updateGoldenOutputMap(string goldenOutputFile);
-    bool readFilterEventData();
-    bool dumpAvData(DemuxFilterMediaEvent event);
-    bool readRecordData(DemuxFilterTsRecordEvent event);
+    bool readFilterEventData(const DemuxFilterEvent& filterEvent);
+    bool dumpAvData(DemuxFilterMediaEvent& event);
+    bool readRecordData(DemuxFilterTsRecordEvent& event);
 
   private:
     struct FilterThreadArgs {
@@ -120,7 +119,6 @@
     sp<IFilter> mFilter;
     std::unique_ptr<FilterMQ> mFilterMQ;
     EventFlag* mFilterMQEventFlag;
-    DemuxFilterEvent mFilterEvent;
 
     android::Mutex mMsgLock;
     android::Mutex mFilterOutputLock;
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.cpp b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
old mode 100644
new mode 100755
index 6cf7d1d..acc524b
--- a/tv/tuner/1.0/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
@@ -85,7 +85,7 @@
         // passed in means the real input config on the transponder connected to the DUT.
         // We want the blind the test to start from lower frequency than this to check the blind
         // scan implementation.
-        resetBlindScanStartingFrequency(config, targetFrequency - 100);
+        resetBlindScanStartingFrequency(config, targetFrequency - 100 * 1000);
     }
 
     Result result = frontend->scan(config.settings, type);
@@ -371,11 +371,13 @@
     mIsSoftwareFe = config.isSoftwareFe;
     bool result = true;
     if (mIsSoftwareFe && testWithDemux) {
-        result &= mDvrTests.openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
-        result &= mDvrTests.configDvrPlayback(mDvrConfig.settings) == success();
-        result &= mDvrTests.getDvrPlaybackMQDescriptor() == success();
-        mDvrTests.startPlaybackInputThread(mDvrConfig.playbackInputFile,
-                                           mDvrConfig.settings.playback());
+        result &=
+                getDvrTests()->openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
+        result &= getDvrTests()->configDvrPlayback(mDvrConfig.settings) == success();
+        result &= getDvrTests()->getDvrPlaybackMQDescriptor() == success();
+        getDvrTests()->startPlaybackInputThread(mDvrConfig.playbackInputFile,
+                                                mDvrConfig.settings.playback());
+        getDvrTests()->startDvrPlayback();
         if (!result) {
             ALOGW("[vts] Software frontend dvr configure failed.");
             return failure();
@@ -398,8 +400,9 @@
     Result status;
     status = mFrontend->stopTune();
     if (mIsSoftwareFe && testWithDemux) {
-        mDvrTests.stopPlaybackThread();
-        mDvrTests.closeDvrPlayback();
+        getDvrTests()->stopPlaybackThread();
+        getDvrTests()->stopDvrPlayback();
+        getDvrTests()->closeDvrPlayback();
     }
     return AssertionResult(status == Result::SUCCESS);
 }
@@ -415,7 +418,6 @@
 
 void FrontendTests::getFrontendIdByType(FrontendType feType, uint32_t& feId) {
     ASSERT_TRUE(getFrontendIds());
-    ASSERT_TRUE(mFeIds.size() > 0);
     for (size_t i = 0; i < mFeIds.size(); i++) {
         ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
         if (mFrontendInfo.type != feType) {
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.h b/tv/tuner/1.0/vts/functional/FrontendTests.h
index 33ff603..c789d94 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.h
@@ -103,7 +103,7 @@
 
     void setService(sp<ITuner> tuner) {
         mService = tuner;
-        mDvrTests.setService(tuner);
+        getDvrTests()->setService(tuner);
         getDefaultSoftwareFrontendPlaybackConfig(mDvrConfig);
     }
 
@@ -124,8 +124,8 @@
     void tuneTest(FrontendConfig frontendConf);
     void scanTest(FrontendConfig frontend, FrontendScanType type);
 
-    void setDvrTests(DvrTests dvrTests) { mDvrTests = dvrTests; }
-    void setDemux(sp<IDemux> demux) { mDvrTests.setDemux(demux); }
+    void setDvrTests(DvrTests* dvrTests) { mExternalDvrTests = dvrTests; }
+    void setDemux(sp<IDemux> demux) { getDvrTests()->setDemux(demux); }
     void setSoftwareFrontendDvrConfig(DvrConfig conf) { mDvrConfig = conf; }
 
   protected:
@@ -147,11 +147,16 @@
         dvrConfig.settings.playback(playbackSettings);
     }
 
+    DvrTests* getDvrTests() {
+        return (mExternalDvrTests != nullptr ? mExternalDvrTests : &mDvrTests);
+    }
+
     sp<IFrontend> mFrontend;
     FrontendInfo mFrontendInfo;
     sp<FrontendCallback> mFrontendCallback;
     hidl_vec<FrontendId> mFeIds;
 
+    DvrTests* mExternalDvrTests = nullptr;
     DvrTests mDvrTests;
     bool mIsSoftwareFe = false;
     DvrConfig mDvrConfig;
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index b39abe3..3e3a4d4 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -177,7 +177,7 @@
             mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[record.dvrSoftwareFeId]);
         }
         ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
-        mFrontendTests.setDvrTests(mDvrTests);
+        mFrontendTests.setDvrTests(&mDvrTests);
     } else {
         dvrSourceConfig = dvrMap[record.dvrSourceId];
         ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrSourceConfig.type, dvrSourceConfig.bufferSize));
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index 7243a42..0b84b58 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -50,7 +50,7 @@
     return true;
 }
 
-AssertionResult filterDataOutputTestBase(FilterTests tests) {
+AssertionResult filterDataOutputTestBase(FilterTests& tests) {
     // Data Verify Module
     std::map<uint32_t, sp<FilterCallback>>::iterator it;
     std::map<uint32_t, sp<FilterCallback>> filterCallbacks = tests.getFilterCallbacks();
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index 2cea181..008879d 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -68,7 +68,7 @@
     // without overriding in the xml config.
     string defaultFeId = "FE_DEFAULT";
     FrontendDvbtSettings dvbtSettings{
-            .frequency = 578000,
+            .frequency = 578000000,
             .transmissionMode = FrontendDvbtTransmissionMode::AUTO,
             .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
             .isHighPriority = true,
diff --git a/tv/tuner/1.1/default/Dvr.cpp b/tv/tuner/1.1/default/Dvr.cpp
index 93f4519..fdb66c1 100644
--- a/tv/tuner/1.1/default/Dvr.cpp
+++ b/tv/tuner/1.1/default/Dvr.cpp
@@ -38,8 +38,8 @@
 }
 
 Dvr::~Dvr() {
-    mDvrThreadRunning = false;
-    lock_guard<mutex> lock(mDvrThreadLock);
+    // make sure thread has joined
+    close();
 }
 
 Return<void> Dvr::getQueueDesc(getQueueDesc_cb _hidl_cb) {
@@ -134,8 +134,7 @@
 
     if (mType == DvrType::PLAYBACK) {
         mDvrThreadRunning = true;
-        pthread_create(&mDvrThread, NULL, __threadLoopPlayback, this);
-        pthread_setname_np(mDvrThread, "playback_waiting_loop");
+        mDvrThread = std::thread(&Dvr::playbackThreadLoop, this);
     } else if (mType == DvrType::RECORD) {
         mRecordStatus = RecordStatus::DATA_READY;
         mDemux->setIsRecording(mType == DvrType::RECORD);
@@ -150,9 +149,11 @@
     ALOGV("%s", __FUNCTION__);
 
     mDvrThreadRunning = false;
-    lock_guard<mutex> lock(mDvrThreadLock);
-
-    mIsRecordStarted = false;
+    if (mDvrThread.joinable()) {
+        mDvrThread.join();
+    }
+    // thread should always be joinable if it is running,
+    // so it should be safe to assume recording stopped.
     mDemux->setIsRecording(false);
 
     return Result::SUCCESS;
@@ -168,9 +169,7 @@
 
 Return<Result> Dvr::close() {
     ALOGV("%s", __FUNCTION__);
-
-    mDvrThreadRunning = false;
-    lock_guard<mutex> lock(mDvrThreadLock);
+    stop();
     return Result::SUCCESS;
 }
 
@@ -197,15 +196,8 @@
     return mDvrEventFlag;
 }
 
-void* Dvr::__threadLoopPlayback(void* user) {
-    Dvr* const self = static_cast<Dvr*>(user);
-    self->playbackThreadLoop();
-    return 0;
-}
-
 void Dvr::playbackThreadLoop() {
     ALOGD("[Dvr] playback threadLoop start.");
-    lock_guard<mutex> lock(mDvrThreadLock);
 
     while (mDvrThreadRunning) {
         uint32_t efState = 0;
diff --git a/tv/tuner/1.1/default/Dvr.h b/tv/tuner/1.1/default/Dvr.h
index 7b7efef..1bbb55c 100644
--- a/tv/tuner/1.1/default/Dvr.h
+++ b/tv/tuner/1.1/default/Dvr.h
@@ -19,7 +19,9 @@
 
 #include <fmq/MessageQueue.h>
 #include <math.h>
+#include <atomic>
 #include <set>
+#include <thread>
 #include "Demux.h"
 #include "Frontend.h"
 #include "Tuner.h"
@@ -115,10 +117,7 @@
      * Each filter handler handles the data filtering/output writing/filterEvent updating.
      */
     void startTpidFilter(vector<uint8_t> data);
-    static void* __threadLoopPlayback(void* user);
-    static void* __threadLoopRecord(void* user);
     void playbackThreadLoop();
-    void recordThreadLoop();
 
     unique_ptr<DvrMQ> mDvrMQ;
     EventFlag* mDvrEventFlag;
@@ -129,7 +128,7 @@
     DvrSettings mDvrSettings;
 
     // Thread handlers
-    pthread_t mDvrThread;
+    std::thread mDvrThread;
 
     // FMQ status local records
     PlaybackStatus mPlaybackStatus;
@@ -137,7 +136,7 @@
     /**
      * If a specific filter's writing loop is still running
      */
-    bool mDvrThreadRunning;
+    std::atomic<bool> mDvrThreadRunning;
     bool mKeepFetchingDataFromFrontend;
     /**
      * Lock to protect writes to the FMQs
@@ -148,13 +147,8 @@
      */
     std::mutex mPlaybackStatusLock;
     std::mutex mRecordStatusLock;
-    std::mutex mDvrThreadLock;
 
     const bool DEBUG_DVR = false;
-
-    // Booleans to check if recording is running.
-    // Recording is ready when both of the following are set to true.
-    bool mIsRecordStarted = false;
 };
 
 }  // namespace implementation
@@ -164,4 +158,4 @@
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_TV_TUNER_V1_1_DVR_H_
\ No newline at end of file
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_1_DVR_H_
diff --git a/tv/tuner/1.1/default/Filter.cpp b/tv/tuner/1.1/default/Filter.cpp
index 7d609ea..e0c785e 100644
--- a/tv/tuner/1.1/default/Filter.cpp
+++ b/tv/tuner/1.1/default/Filter.cpp
@@ -532,7 +532,7 @@
     return mTpid;
 }
 
-void Filter::updateFilterOutput(vector<uint8_t> data) {
+void Filter::updateFilterOutput(const vector<uint8_t>& data) {
     std::lock_guard<std::mutex> lock(mFilterOutputLock);
     mFilterOutput.insert(mFilterOutput.end(), data.begin(), data.end());
 }
@@ -542,7 +542,7 @@
     mPts = pts;
 }
 
-void Filter::updateRecordOutput(vector<uint8_t> data) {
+void Filter::updateRecordOutput(const vector<uint8_t>& data) {
     std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
     mRecordFilterOutput.insert(mRecordFilterOutput.end(), data.begin(), data.end());
 }
@@ -689,9 +689,7 @@
     Result result;
     if (mPts) {
         result = createMediaFilterEventWithIon(mFilterOutput);
-        if (result == Result::SUCCESS) {
-            mFilterOutput.clear();
-        }
+        mFilterOutput.clear();
         return result;
     }
 
@@ -729,6 +727,7 @@
         }
 
         result = createMediaFilterEventWithIon(mPesOutput);
+        mPesOutput.clear();
         if (result != Result::SUCCESS) {
             return result;
         }
@@ -739,7 +738,7 @@
     return Result::SUCCESS;
 }
 
-Result Filter::createMediaFilterEventWithIon(vector<uint8_t> output) {
+Result Filter::createMediaFilterEventWithIon(const vector<uint8_t>& output) {
     if (mUsingSharedAvMem) {
         if (mSharedAvMemHandle.getNativeHandle() == nullptr) {
             return Result::UNKNOWN_ERROR;
@@ -793,7 +792,7 @@
     return Result::SUCCESS;
 }
 
-bool Filter::writeSectionsAndCreateEvent(vector<uint8_t> data) {
+bool Filter::writeSectionsAndCreateEvent(const vector<uint8_t>& data) {
     // TODO check how many sections has been read
     ALOGD("[Filter] section handler");
     std::lock_guard<std::mutex> lock(mFilterEventLock);
@@ -874,7 +873,7 @@
     return nativeHandle;
 }
 
-Result Filter::createIndependentMediaEvents(vector<uint8_t> output) {
+Result Filter::createIndependentMediaEvents(const vector<uint8_t>& output) {
     int av_fd = createAvIonFd(output.size());
     if (av_fd == -1) {
         return Result::UNKNOWN_ERROR;
@@ -912,8 +911,6 @@
     mFilterEvent.events.resize(size + 1);
     mFilterEvent.events[size].media(mediaEvent);
 
-    // Clear and log
-    output.clear();
     mAvBufferCopyCount = 0;
     ::close(av_fd);
     if (DEBUG_FILTER) {
@@ -922,7 +919,7 @@
     return Result::SUCCESS;
 }
 
-Result Filter::createShareMemMediaEvents(vector<uint8_t> output) {
+Result Filter::createShareMemMediaEvents(const vector<uint8_t>& output) {
     // copy the filtered data to the shared buffer
     uint8_t* sharedAvBuffer = getIonBuffer(mSharedAvMemHandle.getNativeHandle()->data[0],
                                            output.size() + mSharedAvMemOffset);
@@ -955,8 +952,6 @@
     mFilterEvent.events.resize(size + 1);
     mFilterEvent.events[size].media(mediaEvent);
 
-    // Clear and log
-    output.clear();
     if (DEBUG_FILTER) {
         ALOGD("[Filter] shared av data length %d", mediaEvent.dataLength);
     }
diff --git a/tv/tuner/1.1/default/Filter.h b/tv/tuner/1.1/default/Filter.h
index 659bebf..1ea2f51 100644
--- a/tv/tuner/1.1/default/Filter.h
+++ b/tv/tuner/1.1/default/Filter.h
@@ -93,8 +93,8 @@
      */
     bool createFilterMQ();
     uint16_t getTpid();
-    void updateFilterOutput(vector<uint8_t> data);
-    void updateRecordOutput(vector<uint8_t> data);
+    void updateFilterOutput(const vector<uint8_t>& data);
+    void updateRecordOutput(const vector<uint8_t>& data);
     void updatePts(uint64_t pts);
     Result startFilterHandler();
     Result startRecordFilterHandler();
@@ -177,7 +177,7 @@
     void deleteEventFlag();
     bool writeDataToFilterMQ(const std::vector<uint8_t>& data);
     bool readDataFromMQ();
-    bool writeSectionsAndCreateEvent(vector<uint8_t> data);
+    bool writeSectionsAndCreateEvent(const vector<uint8_t>& data);
     void maySendFilterStatusCallback();
     DemuxFilterStatus checkFilterStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
                                               uint32_t highThreshold, uint32_t lowThreshold);
@@ -193,9 +193,9 @@
     int createAvIonFd(int size);
     uint8_t* getIonBuffer(int fd, int size);
     native_handle_t* createNativeHandle(int fd);
-    Result createMediaFilterEventWithIon(vector<uint8_t> output);
-    Result createIndependentMediaEvents(vector<uint8_t> output);
-    Result createShareMemMediaEvents(vector<uint8_t> output);
+    Result createMediaFilterEventWithIon(const vector<uint8_t>& output);
+    Result createIndependentMediaEvents(const vector<uint8_t>& output);
+    Result createShareMemMediaEvents(const vector<uint8_t>& output);
     bool sameFile(int fd1, int fd2);
 
     DemuxFilterEvent createMediaEvent();
diff --git a/tv/tuner/1.1/default/Frontend.cpp b/tv/tuner/1.1/default/Frontend.cpp
index e3fbdad..919c956 100644
--- a/tv/tuner/1.1/default/Frontend.cpp
+++ b/tv/tuner/1.1/default/Frontend.cpp
@@ -88,47 +88,61 @@
 
 Return<Result> Frontend::scan(const FrontendSettings& settings, FrontendScanType type) {
     ALOGV("%s", __FUNCTION__);
+
+    // If it's in middle of scanning, stop it first.
+    if (mScanThread.joinable()) {
+        mScanThread.join();
+    }
+
+    mFrontendSettings = settings;
+    mFrontendScanType = type;
+    mScanThread = std::thread(&Frontend::scanThreadLoop, this);
+
+    return Result::SUCCESS;
+}
+
+void Frontend::scanThreadLoop() {
     FrontendScanMessage msg;
 
     if (mIsLocked) {
         msg.isEnd(true);
         mCallback->onScanMessage(FrontendScanMessageType::END, msg);
-        return Result::SUCCESS;
+        return;
     }
 
     uint32_t frequency;
-    switch (settings.getDiscriminator()) {
+    switch (mFrontendSettings.getDiscriminator()) {
         case FrontendSettings::hidl_discriminator::analog:
-            frequency = settings.analog().frequency;
+            frequency = mFrontendSettings.analog().frequency;
             break;
         case FrontendSettings::hidl_discriminator::atsc:
-            frequency = settings.atsc().frequency;
+            frequency = mFrontendSettings.atsc().frequency;
             break;
         case FrontendSettings::hidl_discriminator::atsc3:
-            frequency = settings.atsc3().frequency;
+            frequency = mFrontendSettings.atsc3().frequency;
             break;
         case FrontendSettings::hidl_discriminator::dvbs:
-            frequency = settings.dvbs().frequency;
+            frequency = mFrontendSettings.dvbs().frequency;
             break;
         case FrontendSettings::hidl_discriminator::dvbc:
-            frequency = settings.dvbc().frequency;
+            frequency = mFrontendSettings.dvbc().frequency;
             break;
         case FrontendSettings::hidl_discriminator::dvbt:
-            frequency = settings.dvbt().frequency;
+            frequency = mFrontendSettings.dvbt().frequency;
             break;
         case FrontendSettings::hidl_discriminator::isdbs:
-            frequency = settings.isdbs().frequency;
+            frequency = mFrontendSettings.isdbs().frequency;
             break;
         case FrontendSettings::hidl_discriminator::isdbs3:
-            frequency = settings.isdbs3().frequency;
+            frequency = mFrontendSettings.isdbs3().frequency;
             break;
         case FrontendSettings::hidl_discriminator::isdbt:
-            frequency = settings.isdbt().frequency;
+            frequency = mFrontendSettings.isdbt().frequency;
             break;
     }
 
-    if (type == FrontendScanType::SCAN_BLIND) {
-        frequency += 100;
+    if (mFrontendScanType == FrontendScanType::SCAN_BLIND) {
+        frequency += 100 * 1000;
     }
 
     msg.frequencies({frequency});
@@ -204,8 +218,6 @@
     msg.isLocked(true);
     mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
     mIsLocked = true;
-
-    return Result::SUCCESS;
 }
 
 Return<Result> Frontend::scan_1_1(const FrontendSettings& settings, FrontendScanType type,
@@ -218,6 +230,10 @@
 Return<Result> Frontend::stopScan() {
     ALOGV("%s", __FUNCTION__);
 
+    if (mScanThread.joinable()) {
+        mScanThread.join();
+    }
+
     mIsLocked = false;
     return Result::SUCCESS;
 }
diff --git a/tv/tuner/1.1/default/Frontend.h b/tv/tuner/1.1/default/Frontend.h
index a28fb64..bf739a8 100644
--- a/tv/tuner/1.1/default/Frontend.h
+++ b/tv/tuner/1.1/default/Frontend.h
@@ -20,6 +20,7 @@
 #include <android/hardware/tv/tuner/1.1/IFrontend.h>
 #include <fstream>
 #include <iostream>
+#include <thread>
 #include "Tuner.h"
 
 using namespace std;
@@ -81,13 +82,17 @@
   private:
     virtual ~Frontend();
     bool supportsSatellite();
+    void scanThreadLoop();
+
     sp<IFrontendCallback> mCallback;
     sp<Tuner> mTunerService;
     FrontendType mType = FrontendType::UNDEFINED;
     FrontendId mId = 0;
     bool mIsLocked = false;
     uint32_t mCiCamId;
-
+    std::thread mScanThread;
+    FrontendSettings mFrontendSettings;
+    FrontendScanType mFrontendScanType;
     std::ifstream mFrontendData;
 };
 
diff --git a/tv/tuner/1.1/default/Tuner.cpp b/tv/tuner/1.1/default/Tuner.cpp
index 1e940ba..6d94fbd 100644
--- a/tv/tuner/1.1/default/Tuner.cpp
+++ b/tv/tuner/1.1/default/Tuner.cpp
@@ -264,8 +264,8 @@
     // assign randomly selected values for testing.
     info = {
             .type = mFrontends[frontendId]->getFrontendType(),
-            .minFrequency = 139,
-            .maxFrequency = 1139,
+            .minFrequency = 139000000,
+            .maxFrequency = 1139000000,
             .minSymbolRate = 45,
             .maxSymbolRate = 1145,
             .acquireRange = 30,
diff --git a/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc
index 3718a93..62ee520 100644
--- a/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc
+++ b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc
@@ -3,4 +3,5 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
\ No newline at end of file
+    writepid /dev/cpuset/foreground/tasks
+    onrestart restart media.tuner
diff --git a/tv/tuner/1.1/vts/functional/AndroidTest.xml b/tv/tuner/1.1/vts/functional/AndroidTest.xml
index 3e6878c..848cfc0 100644
--- a/tv/tuner/1.1/vts/functional/AndroidTest.xml
+++ b/tv/tuner/1.1/vts/functional/AndroidTest.xml
@@ -24,6 +24,7 @@
         <option name="cleanup" value="true" />
         <option name="push" value="VtsHalTvTunerV1_1TargetTest->/data/local/tmp/VtsHalTvTunerV1_1TargetTest" />
         <option name="push" value="test.es->/data/local/tmp/test.es" />
+        <option name="push" value="segment000000.ts->/data/local/tmp/segment000000.ts" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
diff --git a/tv/tuner/1.1/vts/functional/DvrTests.cpp b/tv/tuner/1.1/vts/functional/DvrTests.cpp
index 1e478f5..e40e7fd 100644
--- a/tv/tuner/1.1/vts/functional/DvrTests.cpp
+++ b/tv/tuner/1.1/vts/functional/DvrTests.cpp
@@ -123,11 +123,9 @@
     while (mDataOutputBuffer.empty()) {
         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
             EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
-            stopRecordThread();
             return;
         }
     }
-    stopRecordThread();
     ALOGW("[vts] record pass and stop");
 }
 
@@ -204,6 +202,7 @@
 void DvrCallback::stopRecordThread() {
     mKeepReadingRecordFMQ = false;
     mRecordThreadRunning = false;
+    android::Mutex::Autolock autoLock(mRecordThreadLock);
 }
 
 AssertionResult DvrTests::openDvrInDemux(DvrType type, uint32_t bufferSize) {
diff --git a/tv/tuner/1.1/vts/functional/FilterTests.cpp b/tv/tuner/1.1/vts/functional/FilterTests.cpp
index 4dff853..8bdf8f6 100644
--- a/tv/tuner/1.1/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FilterTests.cpp
@@ -64,11 +64,11 @@
     ALOGW("[vts] pass and stop");
 }
 
-void FilterCallback::readFilterEventData() {
+void FilterCallback::readFilterEventData(const DemuxFilterEvent& filterEvent) {
     ALOGW("[vts] reading filter event");
     // todo separate filter handlers
-    for (int i = 0; i < mFilterEvent.events.size(); i++) {
-        auto event = mFilterEvent.events[i];
+    for (int i = 0; i < filterEvent.events.size(); i++) {
+        auto event = filterEvent.events[i];
         switch (event.getDiscriminator()) {
             case DemuxFilterEvent::Event::hidl_discriminator::media:
                 ALOGD("[vts] Media filter event, avMemHandle numFds=%d.",
@@ -79,8 +79,13 @@
                 break;
         }
     }
-    for (int i = 0; i < mFilterEventExt.events.size(); i++) {
-        auto eventExt = mFilterEventExt.events[i];
+}
+
+void FilterCallback::readFilterEventExtData(const DemuxFilterEventExt& filterEventExt) {
+    ALOGW("[vts] reading filter event ext");
+    // todo separate filter handlers
+    for (int i = 0; i < filterEventExt.events.size(); i++) {
+        auto eventExt = filterEventExt.events[i];
         switch (eventExt.getDiscriminator()) {
             case DemuxFilterEventExt::Event::hidl_discriminator::tsRecord:
                 ALOGD("[vts] Extended TS record filter event, pts=%" PRIu64 ", firstMbInSlice=%d",
@@ -114,7 +119,7 @@
     }
 }
 
-bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
+bool FilterCallback::dumpAvData(DemuxFilterMediaEvent& event) {
     uint32_t length = event.dataLength;
     uint32_t offset = event.offset;
     // read data from buffer pointed by a handle
diff --git a/tv/tuner/1.1/vts/functional/FilterTests.h b/tv/tuner/1.1/vts/functional/FilterTests.h
index 72c8129..1a1273e 100644
--- a/tv/tuner/1.1/vts/functional/FilterTests.h
+++ b/tv/tuner/1.1/vts/functional/FilterTests.h
@@ -88,9 +88,8 @@
         android::Mutex::Autolock autoLock(mMsgLock);
         // Temprarily we treat the first coming back filter data on the matching pid a success
         // once all of the MQ are cleared, means we got all the expected output
-        mFilterEvent = filterEvent;
-        mFilterEventExt = filterEventExt;
-        readFilterEventData();
+        readFilterEventData(filterEvent);
+        readFilterEventExtData(filterEventExt);
         mPidFilterOutputCount++;
         mMsgCondition.signal();
         return Void();
@@ -101,8 +100,7 @@
         android::Mutex::Autolock autoLock(mMsgLock);
         // Temprarily we treat the first coming back filter data on the matching pid a success
         // once all of the MQ are cleared, means we got all the expected output
-        mFilterEvent = filterEvent;
-        readFilterEventData();
+        readFilterEventData(filterEvent);
         mPidFilterOutputCount++;
         mMsgCondition.signal();
         return Void();
@@ -115,7 +113,7 @@
     void setFilterId(uint32_t filterId) { mFilterId = filterId; }
     void setFilterInterface(sp<IFilter> filter) { mFilter = filter; }
     void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
-    void setSharedHandle(hidl_handle sharedHandle) { mAvSharedHandle = sharedHandle; }
+    void setSharedHandle(hidl_handle& sharedHandle) { mAvSharedHandle = sharedHandle; }
     void setMemSize(uint64_t size) { mAvSharedMemSize = size; }
 
     void testFilterDataOutput();
@@ -123,15 +121,14 @@
     void testFilterIpCidEvent();
     void testStartIdAfterReconfigure();
 
-    void readFilterEventData();
-    bool dumpAvData(DemuxFilterMediaEvent event);
+    void readFilterEventData(const DemuxFilterEvent& filterEvent);
+    void readFilterEventExtData(const DemuxFilterEventExt& filterEventExt);
+    bool dumpAvData(DemuxFilterMediaEvent& event);
 
   private:
     uint32_t mFilterId;
     sp<IFilter> mFilter;
     FilterEventType mFilterEventType;
-    DemuxFilterEvent mFilterEvent;
-    DemuxFilterEventExt mFilterEventExt;
 
     hidl_handle mAvSharedHandle = NULL;
     uint64_t mAvSharedMemSize = -1;
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.cpp b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
index 7afffb8..9f0f30d 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
@@ -136,7 +136,7 @@
         // passed in means the real input config on the transponder connected to the DUT.
         // We want the blind the test to start from lower frequency than this to check the blind
         // scan implementation.
-        resetBlindScanStartingFrequency(config, targetFrequency - 100);
+        resetBlindScanStartingFrequency(config, targetFrequency - 100 * 1000);
     }
 
     Result result = frontend_1_1->scan_1_1(config.config1_0.settings, type, config.settingsExt1_1);
@@ -438,11 +438,13 @@
     mIsSoftwareFe = config.config1_0.isSoftwareFe;
     bool result = true;
     if (mIsSoftwareFe && testWithDemux) {
-        result &= mDvrTests.openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
-        result &= mDvrTests.configDvrPlayback(mDvrConfig.settings) == success();
-        result &= mDvrTests.getDvrPlaybackMQDescriptor() == success();
-        mDvrTests.startPlaybackInputThread(mDvrConfig.playbackInputFile,
-                                           mDvrConfig.settings.playback());
+        result &=
+                getDvrTests()->openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
+        result &= getDvrTests()->configDvrPlayback(mDvrConfig.settings) == success();
+        result &= getDvrTests()->getDvrPlaybackMQDescriptor() == success();
+        getDvrTests()->startPlaybackInputThread(mDvrConfig.playbackInputFile,
+                                                mDvrConfig.settings.playback());
+        getDvrTests()->startDvrPlayback();
         if (!result) {
             ALOGW("[vts] Software frontend dvr configure failed.");
             return failure();
@@ -457,8 +459,9 @@
     Result status;
     status = mFrontend->stopTune();
     if (mIsSoftwareFe && testWithDemux) {
-        mDvrTests.stopPlaybackThread();
-        mDvrTests.closeDvrPlayback();
+        getDvrTests()->stopPlaybackThread();
+        getDvrTests()->stopDvrPlayback();
+        getDvrTests()->closeDvrPlayback();
     }
     return AssertionResult(status == Result::SUCCESS);
 }
@@ -474,7 +477,6 @@
 
 void FrontendTests::getFrontendIdByType(FrontendType feType, uint32_t& feId) {
     ASSERT_TRUE(getFrontendIds());
-    ASSERT_TRUE(mFeIds.size() > 0);
     for (size_t i = 0; i < mFeIds.size(); i++) {
         ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
         if (mFrontendInfo.type != feType) {
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.h b/tv/tuner/1.1/vts/functional/FrontendTests.h
index 3687389..03e5417 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.h
@@ -106,7 +106,7 @@
 
     void setService(sp<ITuner> tuner) {
         mService = tuner;
-        mDvrTests.setService(tuner);
+        getDvrTests()->setService(tuner);
         getDefaultSoftwareFrontendPlaybackConfig(mDvrConfig);
     }
 
@@ -131,8 +131,8 @@
     void scanTest(FrontendConfig1_1 frontend, FrontendScanType type);
     void getFrontendDtmbCapsTest();
 
-    void setDvrTests(DvrTests dvrTests) { mDvrTests = dvrTests; }
-    void setDemux(sp<IDemux> demux) { mDvrTests.setDemux(demux); }
+    void setDvrTests(DvrTests* dvrTests) { mExternalDvrTests = dvrTests; }
+    void setDemux(sp<IDemux> demux) { getDvrTests()->setDemux(demux); }
     void setSoftwareFrontendDvrConfig(DvrConfig conf) { mDvrConfig = conf; }
 
   protected:
@@ -153,11 +153,16 @@
         dvrConfig.settings.playback(playbackSettings);
     }
 
+    DvrTests* getDvrTests() {
+        return (mExternalDvrTests != nullptr ? mExternalDvrTests : &mDvrTests);
+    }
+
     sp<IFrontend> mFrontend;
     FrontendInfo mFrontendInfo;
     sp<FrontendCallback> mFrontendCallback;
     hidl_vec<FrontendId> mFeIds;
 
+    DvrTests* mExternalDvrTests = nullptr;
     DvrTests mDvrTests;
     bool mIsSoftwareFe = false;
     DvrConfig mDvrConfig;
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
index 1a9def8..41acaa1 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
@@ -147,7 +147,7 @@
             mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[record.dvrSoftwareFeId]);
         }
         ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
-        mFrontendTests.setDvrTests(mDvrTests);
+        mFrontendTests.setDvrTests(&mDvrTests);
     } else {
         dvrSourceConfig = dvrMap[record.dvrSourceId];
         ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrSourceConfig.type, dvrSourceConfig.bufferSize));
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
index 13b9640..d1a9bea 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
@@ -39,7 +39,7 @@
     return ::testing::AssertionSuccess();
 }
 
-AssertionResult filterDataOutputTestBase(FilterTests tests) {
+AssertionResult filterDataOutputTestBase(FilterTests& tests) {
     // Data Verify Module
     std::map<uint64_t, sp<FilterCallback>>::iterator it;
     std::map<uint64_t, sp<FilterCallback>> filterCallbacks = tests.getFilterCallbacks();
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
index 2b5ad46..669fa11 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
@@ -73,7 +73,7 @@
     // without overriding in the xml config.
     string defaultFeId = "FE_DEFAULT";
     FrontendDvbtSettings dvbtSettings{
-            .frequency = 578000,
+            .frequency = 578000000,
             .transmissionMode = FrontendDvbtTransmissionMode::AUTO,
             .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
             .isHighPriority = true,
diff --git a/tv/tuner/aidl/Android.bp b/tv/tuner/aidl/Android.bp
new file mode 100644
index 0000000..c33572d
--- /dev/null
+++ b/tv/tuner/aidl/Android.bp
@@ -0,0 +1,28 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.tv.tuner",
+    vendor_available: true,
+    srcs: ["android/hardware/tv/tuner/*.aidl"],
+    imports: [
+        "android.hardware.common-V2",
+        "android.hardware.common.fmq-V1",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+            srcs_available: true,
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
+}
diff --git a/tv/tuner/aidl/TEST_MAPPING b/tv/tuner/aidl/TEST_MAPPING
new file mode 100644
index 0000000..222c6ed
--- /dev/null
+++ b/tv/tuner/aidl/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "VtsHalTvTunerTargetTest"
+    }
+  ]
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioExtraMetaData.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioExtraMetaData.aidl
new file mode 100644
index 0000000..9db9609
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioExtraMetaData.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable AudioExtraMetaData {
+  byte adFade;
+  byte adPan;
+  char versionTextTag;
+  byte adGainCenter;
+  byte adGainFront;
+  byte adGainSurround;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioStreamType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioStreamType.aidl
new file mode 100644
index 0000000..6c538ea
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioStreamType.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum AudioStreamType {
+  UNDEFINED = 0,
+  PCM = 1,
+  MP3 = 2,
+  MPEG1 = 3,
+  MPEG2 = 4,
+  MPEGH = 5,
+  AAC = 6,
+  AC3 = 7,
+  EAC3 = 8,
+  AC4 = 9,
+  DTS = 10,
+  DTS_HD = 11,
+  WMA = 12,
+  OPUS = 13,
+  VORBIS = 14,
+  DRA = 15,
+  AAC_ADTS = 16,
+  AAC_LATM = 17,
+  AAC_HE_ADTS = 18,
+  AAC_HE_LATM = 19,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AvStreamType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AvStreamType.aidl
new file mode 100644
index 0000000..4d6acff
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AvStreamType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union AvStreamType {
+  android.hardware.tv.tuner.VideoStreamType video = android.hardware.tv.tuner.VideoStreamType.UNDEFINED;
+  android.hardware.tv.tuner.AudioStreamType audio;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant.aidl
new file mode 100644
index 0000000..95ecc51
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum Constant {
+  INVALID_TS_PID = 65535,
+  INVALID_STREAM_ID = 65535,
+  INVALID_FILTER_ID = -1,
+  INVALID_AV_SYNC_ID = -1,
+  INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = -1,
+  INVALID_FIRST_MACROBLOCK_IN_SLICE = -1,
+  INVALID_FRONTEND_SETTING_FREQUENCY = -1,
+  INVALID_IP_FILTER_CONTEXT_ID = -1,
+  INVALID_LTS_ID = -1,
+  INVALID_FRONTEND_ID = -1,
+  INVALID_LNB_ID = -1,
+  INVALID_KEYTOKEN = 0,
+  INVALID_TABINFO_VERSION = -1,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant64Bit.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant64Bit.aidl
new file mode 100644
index 0000000..a56a0cf
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Constant64Bit.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="long") @VintfStability
+enum Constant64Bit {
+  INVALID_FILTER_ID_64BIT = -1,
+  INVALID_AV_SYNC_ID_64BIT = -1,
+  INVALID_PRESENTATION_TIME_STAMP = -1,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DataFormat.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DataFormat.aidl
new file mode 100644
index 0000000..3b8fee4
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DataFormat.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DataFormat {
+  TS = 0,
+  PES = 1,
+  ES = 2,
+  SHV_TLV = 3,
+  UNDEFINED = 4,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterSettings.aidl
new file mode 100644
index 0000000..91a04a4
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterSettings.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxAlpFilterSettings {
+  int packetType;
+  android.hardware.tv.tuner.DemuxAlpLengthType lengthType = android.hardware.tv.tuner.DemuxAlpLengthType.UNDEFINED;
+  android.hardware.tv.tuner.DemuxAlpFilterSettingsFilterSettings filterSettings;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterSettingsFilterSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterSettingsFilterSettings.aidl
new file mode 100644
index 0000000..6b15492
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterSettingsFilterSettings.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxAlpFilterSettingsFilterSettings {
+  boolean noinit;
+  android.hardware.tv.tuner.DemuxFilterSectionSettings section;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterType.aidl
new file mode 100644
index 0000000..f0df497
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpFilterType.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxAlpFilterType {
+  UNDEFINED = 0,
+  SECTION = 1,
+  PTP = 2,
+  PAYLOAD_THROUGH = 3,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpLengthType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpLengthType.aidl
new file mode 100644
index 0000000..ccca6de
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxAlpLengthType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum DemuxAlpLengthType {
+  UNDEFINED = 0,
+  WITHOUT_ADDITIONAL_HEADER = 1,
+  WITH_ADDITIONAL_HEADER = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxCapabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxCapabilities.aidl
new file mode 100644
index 0000000..49afb94
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxCapabilities.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxCapabilities {
+  int numDemux;
+  int numRecord;
+  int numPlayback;
+  int numTsFilter;
+  int numSectionFilter;
+  int numAudioFilter;
+  int numVideoFilter;
+  int numPesFilter;
+  int numPcrFilter;
+  long numBytesInSectionFilter;
+  int filterCaps;
+  int[] linkCaps;
+  boolean bTimeFilter;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterAvSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterAvSettings.aidl
new file mode 100644
index 0000000..3e5df2d
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterAvSettings.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterAvSettings {
+  boolean isPassthrough;
+  boolean isSecureMemory;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl
new file mode 100644
index 0000000..8a05dbd
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterDownloadEvent {
+  int itemId;
+  int downloadId;
+  int mpuSequenceNumber;
+  int itemFragmentIndex;
+  int lastItemFragmentIndex;
+  int dataLength;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl
new file mode 100644
index 0000000..86ce646
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterDownloadSettings {
+  boolean useDownloadId;
+  int downloadId;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterEvent.aidl
new file mode 100644
index 0000000..617f71c
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterEvent.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxFilterEvent {
+  android.hardware.tv.tuner.DemuxFilterSectionEvent section;
+  android.hardware.tv.tuner.DemuxFilterMediaEvent media;
+  android.hardware.tv.tuner.DemuxFilterPesEvent pes;
+  android.hardware.tv.tuner.DemuxFilterTsRecordEvent tsRecord;
+  android.hardware.tv.tuner.DemuxFilterMmtpRecordEvent mmtpRecord;
+  android.hardware.tv.tuner.DemuxFilterDownloadEvent download;
+  android.hardware.tv.tuner.DemuxFilterIpPayloadEvent ipPayload;
+  android.hardware.tv.tuner.DemuxFilterTemiEvent temi;
+  android.hardware.tv.tuner.DemuxFilterMonitorEvent monitorEvent;
+  int startId;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterIpPayloadEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterIpPayloadEvent.aidl
new file mode 100644
index 0000000..9134df3
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterIpPayloadEvent.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterIpPayloadEvent {
+  int dataLength;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMainType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMainType.aidl
new file mode 100644
index 0000000..6abd87b
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMainType.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxFilterMainType {
+  UNDEFINED = 0,
+  TS = 1,
+  MMTP = 2,
+  IP = 4,
+  TLV = 8,
+  ALP = 16,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
new file mode 100644
index 0000000..61a9555
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterMediaEvent {
+  int streamId;
+  boolean isPtsPresent;
+  long pts;
+  boolean isDtsPresent;
+  long dts;
+  long dataLength;
+  long offset;
+  android.hardware.common.NativeHandle avMemory;
+  boolean isSecureMemory;
+  long avDataId;
+  int mpuSequenceNumber;
+  boolean isPesPrivateData;
+  android.hardware.tv.tuner.DemuxFilterMediaEventExtraMetaData extraMetaData;
+  android.hardware.tv.tuner.DemuxFilterScIndexMask scIndexMask;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEventExtraMetaData.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEventExtraMetaData.aidl
new file mode 100644
index 0000000..ab36188
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEventExtraMetaData.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxFilterMediaEventExtraMetaData {
+  boolean noinit;
+  android.hardware.tv.tuner.AudioExtraMetaData audio;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMmtpRecordEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMmtpRecordEvent.aidl
new file mode 100644
index 0000000..4e31ba8
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMmtpRecordEvent.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterMmtpRecordEvent {
+  int scHevcIndexMask;
+  long byteNumber;
+  long pts;
+  int mpuSequenceNumber;
+  int firstMbInSlice;
+  int tsIndexMask;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMonitorEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMonitorEvent.aidl
new file mode 100644
index 0000000..177de7a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMonitorEvent.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxFilterMonitorEvent {
+  android.hardware.tv.tuner.ScramblingStatus scramblingStatus = android.hardware.tv.tuner.ScramblingStatus.UNKNOWN;
+  int cid;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMonitorEventType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMonitorEventType.aidl
new file mode 100644
index 0000000..5d27f76
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMonitorEventType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxFilterMonitorEventType {
+  SCRAMBLING_STATUS = 1,
+  IP_CID_CHANGE = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterPesDataSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterPesDataSettings.aidl
new file mode 100644
index 0000000..2420142
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterPesDataSettings.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterPesDataSettings {
+  int streamId;
+  boolean isRaw;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterPesEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterPesEvent.aidl
new file mode 100644
index 0000000..3ddd5e0
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterPesEvent.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterPesEvent {
+  int streamId;
+  int dataLength;
+  int mpuSequenceNumber;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterRecordSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterRecordSettings.aidl
new file mode 100644
index 0000000..02c478f
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterRecordSettings.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterRecordSettings {
+  int tsIndexMask;
+  android.hardware.tv.tuner.DemuxRecordScIndexType scIndexType = android.hardware.tv.tuner.DemuxRecordScIndexType.NONE;
+  android.hardware.tv.tuner.DemuxFilterScIndexMask scIndexMask;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterScIndexMask.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterScIndexMask.aidl
new file mode 100644
index 0000000..371e075
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterScIndexMask.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxFilterScIndexMask {
+  int scIndex;
+  int scAvc;
+  int scHevc;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionBits.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionBits.aidl
new file mode 100644
index 0000000..b666c7b
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionBits.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterSectionBits {
+  byte[] filter;
+  byte[] mask;
+  byte[] mode;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl
new file mode 100644
index 0000000..199a09c
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterSectionEvent {
+  int tableId;
+  int version;
+  int sectionNum;
+  long dataLength;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionSettings.aidl
new file mode 100644
index 0000000..2858565
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionSettings.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterSectionSettings {
+  android.hardware.tv.tuner.DemuxFilterSectionSettingsCondition condition;
+  boolean isCheckCrc;
+  boolean isRepeat;
+  boolean isRaw;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionSettingsCondition.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionSettingsCondition.aidl
new file mode 100644
index 0000000..0b101de
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionSettingsCondition.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxFilterSectionSettingsCondition {
+  android.hardware.tv.tuner.DemuxFilterSectionBits sectionBits;
+  android.hardware.tv.tuner.DemuxFilterSectionSettingsConditionTableInfo tableInfo;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionSettingsConditionTableInfo.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionSettingsConditionTableInfo.aidl
new file mode 100644
index 0000000..82d30cb
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionSettingsConditionTableInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterSectionSettingsConditionTableInfo {
+  int tableId;
+  int version;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSettings.aidl
new file mode 100644
index 0000000..c12fde2
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSettings.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxFilterSettings {
+  android.hardware.tv.tuner.DemuxTsFilterSettings ts;
+  android.hardware.tv.tuner.DemuxMmtpFilterSettings mmtp;
+  android.hardware.tv.tuner.DemuxIpFilterSettings ip;
+  android.hardware.tv.tuner.DemuxTlvFilterSettings tlv;
+  android.hardware.tv.tuner.DemuxAlpFilterSettings alp;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterStatus.aidl
new file mode 100644
index 0000000..36b40ea
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum DemuxFilterStatus {
+  DATA_READY = 1,
+  LOW_WATER = 2,
+  HIGH_WATER = 4,
+  OVERFLOW = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSubType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSubType.aidl
new file mode 100644
index 0000000..2e2a774
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSubType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxFilterSubType {
+  android.hardware.tv.tuner.DemuxTsFilterType tsFilterType = android.hardware.tv.tuner.DemuxTsFilterType.UNDEFINED;
+  android.hardware.tv.tuner.DemuxMmtpFilterType mmtpFilterType;
+  android.hardware.tv.tuner.DemuxIpFilterType ipFilterType;
+  android.hardware.tv.tuner.DemuxTlvFilterType tlvFilterType;
+  android.hardware.tv.tuner.DemuxAlpFilterType alpFilterType;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterTemiEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterTemiEvent.aidl
new file mode 100644
index 0000000..ce15861
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterTemiEvent.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterTemiEvent {
+  long pts;
+  byte descrTag;
+  byte[] descrData;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterTsRecordEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterTsRecordEvent.aidl
new file mode 100644
index 0000000..5c27faf
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterTsRecordEvent.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterTsRecordEvent {
+  android.hardware.tv.tuner.DemuxPid pid;
+  int tsIndexMask;
+  android.hardware.tv.tuner.DemuxFilterScIndexMask scIndexMask;
+  long byteNumber;
+  long pts;
+  int firstMbInSlice;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterType.aidl
new file mode 100644
index 0000000..b2f499d
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxFilterType {
+  android.hardware.tv.tuner.DemuxFilterMainType mainType = android.hardware.tv.tuner.DemuxFilterMainType.UNDEFINED;
+  android.hardware.tv.tuner.DemuxFilterSubType subType;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpAddress.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpAddress.aidl
new file mode 100644
index 0000000..a044a19
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpAddress.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxIpAddress {
+  android.hardware.tv.tuner.DemuxIpAddressIpAddress srcIpAddress;
+  android.hardware.tv.tuner.DemuxIpAddressIpAddress dstIpAddress;
+  int srcPort;
+  int dstPort;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpAddressIpAddress.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpAddressIpAddress.aidl
new file mode 100644
index 0000000..62de088
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpAddressIpAddress.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxIpAddressIpAddress {
+  byte[] v4 = {};
+  byte[] v6;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterSettings.aidl
new file mode 100644
index 0000000..2b0610b
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterSettings.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxIpFilterSettings {
+  android.hardware.tv.tuner.DemuxIpAddress ipAddr;
+  android.hardware.tv.tuner.DemuxIpFilterSettingsFilterSettings filterSettings;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterSettingsFilterSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterSettingsFilterSettings.aidl
new file mode 100644
index 0000000..daac284
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterSettingsFilterSettings.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxIpFilterSettingsFilterSettings {
+  boolean noinit;
+  android.hardware.tv.tuner.DemuxFilterSectionSettings section;
+  boolean bPassthrough;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterType.aidl
new file mode 100644
index 0000000..b78ac9a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxIpFilterType.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxIpFilterType {
+  UNDEFINED = 0,
+  SECTION = 1,
+  NTP = 2,
+  IP_PAYLOAD = 3,
+  IP = 4,
+  PAYLOAD_THROUGH = 5,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterSettings.aidl
new file mode 100644
index 0000000..b22c564
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterSettings.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxMmtpFilterSettings {
+  int mmtpPid;
+  android.hardware.tv.tuner.DemuxMmtpFilterSettingsFilterSettings filterSettings;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterSettingsFilterSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterSettingsFilterSettings.aidl
new file mode 100644
index 0000000..4b23306
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterSettingsFilterSettings.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxMmtpFilterSettingsFilterSettings {
+  boolean noinit;
+  android.hardware.tv.tuner.DemuxFilterSectionSettings section;
+  android.hardware.tv.tuner.DemuxFilterAvSettings av;
+  android.hardware.tv.tuner.DemuxFilterPesDataSettings pesData;
+  android.hardware.tv.tuner.DemuxFilterRecordSettings record;
+  android.hardware.tv.tuner.DemuxFilterDownloadSettings download;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterType.aidl
new file mode 100644
index 0000000..7e9e3a6
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxMmtpFilterType.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxMmtpFilterType {
+  UNDEFINED = 0,
+  SECTION = 1,
+  PES = 2,
+  MMTP = 3,
+  AUDIO = 4,
+  VIDEO = 5,
+  RECORD = 6,
+  DOWNLOAD = 7,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxPid.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxPid.aidl
new file mode 100644
index 0000000..c452f35
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxPid.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxPid {
+  int tPid;
+  int mmtpPid;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxQueueNotifyBits.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxQueueNotifyBits.aidl
new file mode 100644
index 0000000..bcd0aeb
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxQueueNotifyBits.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxQueueNotifyBits {
+  DATA_READY = 1,
+  DATA_CONSUMED = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxRecordScIndexType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxRecordScIndexType.aidl
new file mode 100644
index 0000000..30ec29a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxRecordScIndexType.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxRecordScIndexType {
+  NONE = 0,
+  SC = 1,
+  SC_HEVC = 2,
+  SC_AVC = 3,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScAvcIndex.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScAvcIndex.aidl
new file mode 100644
index 0000000..651b66c
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScAvcIndex.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxScAvcIndex {
+  UNDEFINED = 0,
+  I_SLICE = 1,
+  P_SLICE = 2,
+  B_SLICE = 4,
+  SI_SLICE = 8,
+  SP_SLICE = 16,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScHevcIndex.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScHevcIndex.aidl
new file mode 100644
index 0000000..670b34e
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScHevcIndex.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxScHevcIndex {
+  UNDEFINED = 0,
+  SPS = 1,
+  AUD = 2,
+  SLICE_CE_BLA_W_LP = 4,
+  SLICE_BLA_W_RADL = 8,
+  SLICE_BLA_N_LP = 16,
+  SLICE_IDR_W_RADL = 32,
+  SLICE_IDR_N_LP = 64,
+  SLICE_TRAIL_CRA = 128,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScIndex.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScIndex.aidl
new file mode 100644
index 0000000..25f0585
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxScIndex.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxScIndex {
+  UNDEFINED = 0,
+  I_FRAME = 1,
+  P_FRAME = 2,
+  B_FRAME = 4,
+  SEQUENCE = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterSettings.aidl
new file mode 100644
index 0000000..ddb61ce
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterSettings.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxTlvFilterSettings {
+  int packetType;
+  boolean isCompressedIpPacket;
+  android.hardware.tv.tuner.DemuxTlvFilterSettingsFilterSettings filterSettings;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterSettingsFilterSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterSettingsFilterSettings.aidl
new file mode 100644
index 0000000..a9d3198
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterSettingsFilterSettings.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxTlvFilterSettingsFilterSettings {
+  boolean noinit;
+  android.hardware.tv.tuner.DemuxFilterSectionSettings section;
+  boolean bPassthrough;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterType.aidl
new file mode 100644
index 0000000..a4e1ff1
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTlvFilterType.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxTlvFilterType {
+  UNDEFINED = 0,
+  SECTION = 1,
+  TLV = 2,
+  PAYLOAD_THROUGH = 3,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterSettings.aidl
new file mode 100644
index 0000000..d8d424f
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterSettings.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable DemuxTsFilterSettings {
+  int tpid;
+  android.hardware.tv.tuner.DemuxTsFilterSettingsFilterSettings filterSettings;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterSettingsFilterSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterSettingsFilterSettings.aidl
new file mode 100644
index 0000000..5d81bb6
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterSettingsFilterSettings.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DemuxTsFilterSettingsFilterSettings {
+  boolean noinit;
+  android.hardware.tv.tuner.DemuxFilterSectionSettings section;
+  android.hardware.tv.tuner.DemuxFilterAvSettings av;
+  android.hardware.tv.tuner.DemuxFilterPesDataSettings pesData;
+  android.hardware.tv.tuner.DemuxFilterRecordSettings record;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterType.aidl
new file mode 100644
index 0000000..8b806bf
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsFilterType.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxTsFilterType {
+  UNDEFINED = 0,
+  SECTION = 1,
+  PES = 2,
+  TS = 3,
+  AUDIO = 4,
+  VIDEO = 5,
+  PCR = 6,
+  RECORD = 7,
+  TEMI = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsIndex.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsIndex.aidl
new file mode 100644
index 0000000..ed03477
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxTsIndex.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DemuxTsIndex {
+  FIRST_PACKET = 1,
+  PAYLOAD_UNIT_START_INDICATOR = 2,
+  CHANGE_TO_NOT_SCRAMBLED = 4,
+  CHANGE_TO_EVEN_SCRAMBLED = 8,
+  CHANGE_TO_ODD_SCRAMBLED = 16,
+  DISCONTINUITY_INDICATOR = 32,
+  RANDOM_ACCESS_INDICATOR = 64,
+  PRIORITY_INDICATOR = 128,
+  PCR_FLAG = 256,
+  OPCR_FLAG = 512,
+  SPLICING_POINT_FLAG = 1024,
+  PRIVATE_DATA = 2048,
+  ADAPTATION_EXTENSION_FLAG = 4096,
+  MPT_INDEX_MPT = 65536,
+  MPT_INDEX_VIDEO = 131072,
+  MPT_INDEX_AUDIO = 262144,
+  MPT_INDEX_TIMESTAMP_TARGET_VIDEO = 524288,
+  MPT_INDEX_TIMESTAMP_TARGET_AUDIO = 1048576,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DvrSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DvrSettings.aidl
new file mode 100644
index 0000000..26f864a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DvrSettings.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union DvrSettings {
+  android.hardware.tv.tuner.RecordSettings record;
+  android.hardware.tv.tuner.PlaybackSettings playback;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DvrType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DvrType.aidl
new file mode 100644
index 0000000..3a0c1e4
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DvrType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum DvrType {
+  RECORD = 0,
+  PLAYBACK = 1,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FilterDelayHint.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FilterDelayHint.aidl
new file mode 100644
index 0000000..1fdafd2
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FilterDelayHint.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FilterDelayHint {
+  android.hardware.tv.tuner.FilterDelayHintType hintType = android.hardware.tv.tuner.FilterDelayHintType.INVALID;
+  int hintValue;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FilterDelayHintType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FilterDelayHintType.aidl
new file mode 100644
index 0000000..8c5a3f5
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FilterDelayHintType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FilterDelayHintType {
+  INVALID = 0,
+  TIME_DELAY_IN_MS = 1,
+  DATA_SIZE_DELAY_IN_BYTES = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogAftFlag.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogAftFlag.aidl
new file mode 100644
index 0000000..6b32110
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogAftFlag.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendAnalogAftFlag {
+  UNDEFINED = 0,
+  AFT_TRUE = 1,
+  AFT_FALSE = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogCapabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogCapabilities.aidl
new file mode 100644
index 0000000..46131be
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogCapabilities.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendAnalogCapabilities {
+  int typeCap;
+  int sifStandardCap;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogSettings.aidl
new file mode 100644
index 0000000..33e9347
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogSettings.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendAnalogSettings {
+  long frequency;
+  long endFrequency;
+  android.hardware.tv.tuner.FrontendSpectralInversion inversion = android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
+  android.hardware.tv.tuner.FrontendAnalogType type = android.hardware.tv.tuner.FrontendAnalogType.UNDEFINED;
+  android.hardware.tv.tuner.FrontendAnalogAftFlag aftFlag = android.hardware.tv.tuner.FrontendAnalogAftFlag.UNDEFINED;
+  android.hardware.tv.tuner.FrontendAnalogSifStandard sifStandard = android.hardware.tv.tuner.FrontendAnalogSifStandard.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogSifStandard.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogSifStandard.aidl
new file mode 100644
index 0000000..3502522
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogSifStandard.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendAnalogSifStandard {
+  UNDEFINED = 0,
+  AUTO = 1,
+  BG = 2,
+  BG_A2 = 4,
+  BG_NICAM = 8,
+  I = 16,
+  DK = 32,
+  DK1_A2 = 64,
+  DK2_A2 = 128,
+  DK3_A2 = 256,
+  DK_NICAM = 512,
+  L = 1024,
+  M = 2048,
+  M_BTSC = 4096,
+  M_A2 = 8192,
+  M_EIAJ = 16384,
+  I_NICAM = 32768,
+  L_NICAM = 65536,
+  L_PRIME = 131072,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogType.aidl
new file mode 100644
index 0000000..33fd93d
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAnalogType.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendAnalogType {
+  UNDEFINED = 0,
+  AUTO = 1,
+  PAL = 2,
+  PAL_M = 4,
+  PAL_N = 8,
+  PAL_60 = 16,
+  NTSC = 32,
+  NTSC_443 = 64,
+  SECAM = 128,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Bandwidth.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Bandwidth.aidl
new file mode 100644
index 0000000..51a3fc5
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Bandwidth.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendAtsc3Bandwidth {
+  UNDEFINED = 0,
+  AUTO = 1,
+  BANDWIDTH_6MHZ = 2,
+  BANDWIDTH_7MHZ = 4,
+  BANDWIDTH_8MHZ = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Capabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Capabilities.aidl
new file mode 100644
index 0000000..b2a25c7
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Capabilities.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendAtsc3Capabilities {
+  int bandwidthCap;
+  int modulationCap;
+  int timeInterleaveModeCap;
+  int codeRateCap;
+  int fecCap;
+  byte demodOutputFormatCap;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3CodeRate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3CodeRate.aidl
new file mode 100644
index 0000000..aec0718
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3CodeRate.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendAtsc3CodeRate {
+  UNDEFINED = 0,
+  AUTO = 1,
+  CODERATE_2_15 = 2,
+  CODERATE_3_15 = 4,
+  CODERATE_4_15 = 8,
+  CODERATE_5_15 = 16,
+  CODERATE_6_15 = 32,
+  CODERATE_7_15 = 64,
+  CODERATE_8_15 = 128,
+  CODERATE_9_15 = 256,
+  CODERATE_10_15 = 512,
+  CODERATE_11_15 = 1024,
+  CODERATE_12_15 = 2048,
+  CODERATE_13_15 = 4096,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3DemodOutputFormat.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3DemodOutputFormat.aidl
new file mode 100644
index 0000000..8702a49
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3DemodOutputFormat.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum FrontendAtsc3DemodOutputFormat {
+  UNDEFINED = 0,
+  ATSC3_LINKLAYER_PACKET = 1,
+  BASEBAND_PACKET = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Fec.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Fec.aidl
new file mode 100644
index 0000000..a2c140a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Fec.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendAtsc3Fec {
+  UNDEFINED = 0,
+  AUTO = 1,
+  BCH_LDPC_16K = 2,
+  BCH_LDPC_64K = 4,
+  CRC_LDPC_16K = 8,
+  CRC_LDPC_64K = 16,
+  LDPC_16K = 32,
+  LDPC_64K = 64,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Modulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Modulation.aidl
new file mode 100644
index 0000000..09e513d
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Modulation.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendAtsc3Modulation {
+  UNDEFINED = 0,
+  AUTO = 1,
+  MOD_QPSK = 2,
+  MOD_16QAM = 4,
+  MOD_64QAM = 8,
+  MOD_256QAM = 16,
+  MOD_1024QAM = 32,
+  MOD_4096QAM = 64,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3PlpSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3PlpSettings.aidl
new file mode 100644
index 0000000..6301f96
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3PlpSettings.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendAtsc3PlpSettings {
+  int plpId;
+  android.hardware.tv.tuner.FrontendAtsc3Modulation modulation = android.hardware.tv.tuner.FrontendAtsc3Modulation.UNDEFINED;
+  android.hardware.tv.tuner.FrontendAtsc3TimeInterleaveMode interleaveMode = android.hardware.tv.tuner.FrontendAtsc3TimeInterleaveMode.UNDEFINED;
+  android.hardware.tv.tuner.FrontendAtsc3CodeRate codeRate = android.hardware.tv.tuner.FrontendAtsc3CodeRate.UNDEFINED;
+  android.hardware.tv.tuner.FrontendAtsc3Fec fec = android.hardware.tv.tuner.FrontendAtsc3Fec.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Settings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Settings.aidl
new file mode 100644
index 0000000..3cbb0d0
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3Settings.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendAtsc3Settings {
+  long frequency;
+  long endFrequency;
+  android.hardware.tv.tuner.FrontendAtsc3Bandwidth bandwidth = android.hardware.tv.tuner.FrontendAtsc3Bandwidth.UNDEFINED;
+  android.hardware.tv.tuner.FrontendSpectralInversion inversion = android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
+  android.hardware.tv.tuner.FrontendAtsc3DemodOutputFormat demodOutputFormat = android.hardware.tv.tuner.FrontendAtsc3DemodOutputFormat.UNDEFINED;
+  android.hardware.tv.tuner.FrontendAtsc3PlpSettings[] plpSettings;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3TimeInterleaveMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3TimeInterleaveMode.aidl
new file mode 100644
index 0000000..a9747f0
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtsc3TimeInterleaveMode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendAtsc3TimeInterleaveMode {
+  UNDEFINED = 0,
+  AUTO = 1,
+  CTI = 2,
+  HTI = 4,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscCapabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscCapabilities.aidl
new file mode 100644
index 0000000..c24afae
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscCapabilities.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendAtscCapabilities {
+  int modulationCap;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscModulation.aidl
new file mode 100644
index 0000000..426fe20
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscModulation.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendAtscModulation {
+  UNDEFINED = 0,
+  AUTO = 1,
+  MOD_8VSB = 4,
+  MOD_16VSB = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscSettings.aidl
new file mode 100644
index 0000000..9121c12
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendAtscSettings.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendAtscSettings {
+  long frequency;
+  long endFrequency;
+  android.hardware.tv.tuner.FrontendSpectralInversion inversion = android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
+  android.hardware.tv.tuner.FrontendAtscModulation modulation = android.hardware.tv.tuner.FrontendAtscModulation.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendBandwidth.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendBandwidth.aidl
new file mode 100644
index 0000000..5355637
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendBandwidth.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendBandwidth {
+  android.hardware.tv.tuner.FrontendAtsc3Bandwidth atsc3 = android.hardware.tv.tuner.FrontendAtsc3Bandwidth.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbcBandwidth dvbc;
+  android.hardware.tv.tuner.FrontendDvbtBandwidth dvbt;
+  android.hardware.tv.tuner.FrontendIsdbtBandwidth isdbt;
+  android.hardware.tv.tuner.FrontendDtmbBandwidth dtmb;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendCableTimeInterleaveMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendCableTimeInterleaveMode.aidl
new file mode 100644
index 0000000..ff71df3
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendCableTimeInterleaveMode.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendCableTimeInterleaveMode {
+  UNDEFINED = 0,
+  AUTO = 1,
+  INTERLEAVING_128_1_0 = 2,
+  INTERLEAVING_128_1_1 = 4,
+  INTERLEAVING_64_2 = 8,
+  INTERLEAVING_32_4 = 16,
+  INTERLEAVING_16_8 = 32,
+  INTERLEAVING_8_16 = 64,
+  INTERLEAVING_128_2 = 128,
+  INTERLEAVING_128_3 = 256,
+  INTERLEAVING_128_4 = 512,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendCapabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendCapabilities.aidl
new file mode 100644
index 0000000..c013cd1
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendCapabilities.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendCapabilities {
+  android.hardware.tv.tuner.FrontendAnalogCapabilities analogCaps;
+  android.hardware.tv.tuner.FrontendAtscCapabilities atscCaps;
+  android.hardware.tv.tuner.FrontendAtsc3Capabilities atsc3Caps;
+  android.hardware.tv.tuner.FrontendDtmbCapabilities dtmbCaps;
+  android.hardware.tv.tuner.FrontendDvbsCapabilities dvbsCaps;
+  android.hardware.tv.tuner.FrontendDvbcCapabilities dvbcCaps;
+  android.hardware.tv.tuner.FrontendDvbtCapabilities dvbtCaps;
+  android.hardware.tv.tuner.FrontendIsdbsCapabilities isdbsCaps;
+  android.hardware.tv.tuner.FrontendIsdbs3Capabilities isdbs3Caps;
+  android.hardware.tv.tuner.FrontendIsdbtCapabilities isdbtCaps;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbBandwidth.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbBandwidth.aidl
new file mode 100644
index 0000000..18d71d2
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbBandwidth.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDtmbBandwidth {
+  UNDEFINED = 0,
+  AUTO = 1,
+  BANDWIDTH_8MHZ = 2,
+  BANDWIDTH_6MHZ = 4,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbCapabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbCapabilities.aidl
new file mode 100644
index 0000000..8d35104
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbCapabilities.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendDtmbCapabilities {
+  int transmissionModeCap;
+  int bandwidthCap;
+  int modulationCap;
+  int codeRateCap;
+  int guardIntervalCap;
+  int interleaveModeCap;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbCodeRate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbCodeRate.aidl
new file mode 100644
index 0000000..c9454e7
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbCodeRate.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDtmbCodeRate {
+  UNDEFINED = 0,
+  AUTO = 1,
+  CODERATE_2_5 = 2,
+  CODERATE_3_5 = 4,
+  CODERATE_4_5 = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbGuardInterval.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbGuardInterval.aidl
new file mode 100644
index 0000000..872eb6a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbGuardInterval.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDtmbGuardInterval {
+  UNDEFINED = 0,
+  AUTO = 1,
+  PN_420_VARIOUS = 2,
+  PN_595_CONST = 4,
+  PN_945_VARIOUS = 8,
+  PN_420_CONST = 16,
+  PN_945_CONST = 32,
+  PN_RESERVED = 64,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbModulation.aidl
new file mode 100644
index 0000000..088aac5
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbModulation.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDtmbModulation {
+  UNDEFINED = 0,
+  AUTO = 1,
+  CONSTELLATION_4QAM = 2,
+  CONSTELLATION_4QAM_NR = 4,
+  CONSTELLATION_16QAM = 8,
+  CONSTELLATION_32QAM = 16,
+  CONSTELLATION_64QAM = 32,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbSettings.aidl
new file mode 100644
index 0000000..5f9b775
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbSettings.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendDtmbSettings {
+  long frequency;
+  long endFrequency;
+  android.hardware.tv.tuner.FrontendSpectralInversion inversion = android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDtmbTransmissionMode transmissionMode = android.hardware.tv.tuner.FrontendDtmbTransmissionMode.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDtmbBandwidth bandwidth = android.hardware.tv.tuner.FrontendDtmbBandwidth.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDtmbModulation modulation = android.hardware.tv.tuner.FrontendDtmbModulation.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDtmbCodeRate codeRate = android.hardware.tv.tuner.FrontendDtmbCodeRate.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDtmbGuardInterval guardInterval = android.hardware.tv.tuner.FrontendDtmbGuardInterval.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDtmbTimeInterleaveMode interleaveMode = android.hardware.tv.tuner.FrontendDtmbTimeInterleaveMode.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTimeInterleaveMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTimeInterleaveMode.aidl
new file mode 100644
index 0000000..8321ad0
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTimeInterleaveMode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDtmbTimeInterleaveMode {
+  UNDEFINED = 0,
+  AUTO = 1,
+  TIMER_INT_240 = 2,
+  TIMER_INT_720 = 4,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTransmissionMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTransmissionMode.aidl
new file mode 100644
index 0000000..5298291
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDtmbTransmissionMode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDtmbTransmissionMode {
+  UNDEFINED = 0,
+  AUTO = 1,
+  C1 = 2,
+  C3780 = 4,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcAnnex.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcAnnex.aidl
new file mode 100644
index 0000000..cdfedb6
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcAnnex.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum FrontendDvbcAnnex {
+  UNDEFINED = 0,
+  A = 1,
+  B = 2,
+  C = 4,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcBandwidth.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcBandwidth.aidl
new file mode 100644
index 0000000..f0fe460
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcBandwidth.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbcBandwidth {
+  UNDEFINED = 0,
+  BANDWIDTH_5MHZ = 1,
+  BANDWIDTH_6MHZ = 2,
+  BANDWIDTH_7MHZ = 4,
+  BANDWIDTH_8MHZ = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcCapabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcCapabilities.aidl
new file mode 100644
index 0000000..0c0e3ee
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcCapabilities.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendDvbcCapabilities {
+  int modulationCap;
+  long fecCap;
+  byte annexCap;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcModulation.aidl
new file mode 100644
index 0000000..0871777
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcModulation.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbcModulation {
+  UNDEFINED = 0,
+  AUTO = 1,
+  MOD_16QAM = 2,
+  MOD_32QAM = 4,
+  MOD_64QAM = 8,
+  MOD_128QAM = 16,
+  MOD_256QAM = 32,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcOuterFec.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcOuterFec.aidl
new file mode 100644
index 0000000..f1e92c9
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcOuterFec.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbcOuterFec {
+  UNDEFINED = 0,
+  OUTER_FEC_NONE = 1,
+  OUTER_FEC_RS = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcSettings.aidl
new file mode 100644
index 0000000..6b2caed
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbcSettings.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendDvbcSettings {
+  long frequency;
+  long endFrequency;
+  android.hardware.tv.tuner.FrontendDvbcModulation modulation = android.hardware.tv.tuner.FrontendDvbcModulation.UNDEFINED;
+  android.hardware.tv.tuner.FrontendInnerFec fec = android.hardware.tv.tuner.FrontendInnerFec.FEC_UNDEFINED;
+  int symbolRate;
+  android.hardware.tv.tuner.FrontendDvbcOuterFec outerFec = android.hardware.tv.tuner.FrontendDvbcOuterFec.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbcAnnex annex = android.hardware.tv.tuner.FrontendDvbcAnnex.UNDEFINED;
+  android.hardware.tv.tuner.FrontendSpectralInversion inversion = android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
+  android.hardware.tv.tuner.FrontendCableTimeInterleaveMode interleaveMode = android.hardware.tv.tuner.FrontendCableTimeInterleaveMode.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbcBandwidth bandwidth = android.hardware.tv.tuner.FrontendDvbcBandwidth.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsCapabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsCapabilities.aidl
new file mode 100644
index 0000000..43e8aee
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsCapabilities.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendDvbsCapabilities {
+  int modulationCap;
+  long innerfecCap;
+  byte standard;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsCodeRate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsCodeRate.aidl
new file mode 100644
index 0000000..4c3d4e4
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsCodeRate.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendDvbsCodeRate {
+  android.hardware.tv.tuner.FrontendInnerFec fec = android.hardware.tv.tuner.FrontendInnerFec.FEC_UNDEFINED;
+  boolean isLinear;
+  boolean isShortFrames;
+  int bitsPer1000Symbol;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsModulation.aidl
new file mode 100644
index 0000000..25951cc
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsModulation.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbsModulation {
+  UNDEFINED = 0,
+  AUTO = 1,
+  MOD_QPSK = 2,
+  MOD_8PSK = 4,
+  MOD_16QAM = 8,
+  MOD_16PSK = 16,
+  MOD_32PSK = 32,
+  MOD_ACM = 64,
+  MOD_8APSK = 128,
+  MOD_16APSK = 256,
+  MOD_32APSK = 512,
+  MOD_64APSK = 1024,
+  MOD_128APSK = 2048,
+  MOD_256APSK = 4096,
+  MOD_RESERVED = 8192,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsPilot.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsPilot.aidl
new file mode 100644
index 0000000..4f2c6eb
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsPilot.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbsPilot {
+  UNDEFINED = 0,
+  ON = 1,
+  OFF = 2,
+  AUTO = 3,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsRolloff.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsRolloff.aidl
new file mode 100644
index 0000000..56ee37b
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsRolloff.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbsRolloff {
+  UNDEFINED = 0,
+  ROLLOFF_0_35 = 1,
+  ROLLOFF_0_25 = 2,
+  ROLLOFF_0_20 = 3,
+  ROLLOFF_0_15 = 4,
+  ROLLOFF_0_10 = 5,
+  ROLLOFF_0_5 = 6,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsScanType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsScanType.aidl
new file mode 100644
index 0000000..110b1d8
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsScanType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbsScanType {
+  UNDEFINED = 0,
+  DIRECT = 1,
+  DISEQC = 2,
+  UNICABLE = 3,
+  JESS = 4,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsSettings.aidl
new file mode 100644
index 0000000..dab8888
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsSettings.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendDvbsSettings {
+  long frequency;
+  long endFrequency;
+  android.hardware.tv.tuner.FrontendSpectralInversion inversion = android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbsModulation modulation = android.hardware.tv.tuner.FrontendDvbsModulation.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbsCodeRate coderate;
+  int symbolRate;
+  android.hardware.tv.tuner.FrontendDvbsRolloff rolloff = android.hardware.tv.tuner.FrontendDvbsRolloff.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbsPilot pilot = android.hardware.tv.tuner.FrontendDvbsPilot.UNDEFINED;
+  int inputStreamId;
+  android.hardware.tv.tuner.FrontendDvbsStandard standard = android.hardware.tv.tuner.FrontendDvbsStandard.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbsVcmMode vcmMode = android.hardware.tv.tuner.FrontendDvbsVcmMode.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbsScanType scanType = android.hardware.tv.tuner.FrontendDvbsScanType.UNDEFINED;
+  boolean isDiseqcRxMessage;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsStandard.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsStandard.aidl
new file mode 100644
index 0000000..b9cb657
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsStandard.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum FrontendDvbsStandard {
+  UNDEFINED = 0,
+  AUTO = 1,
+  S = 2,
+  S2 = 4,
+  S2X = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsVcmMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsVcmMode.aidl
new file mode 100644
index 0000000..2cbff7c
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbsVcmMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbsVcmMode {
+  UNDEFINED = 0,
+  AUTO = 1,
+  MANUAL = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtBandwidth.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtBandwidth.aidl
new file mode 100644
index 0000000..f5d14e8
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtBandwidth.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbtBandwidth {
+  UNDEFINED = 0,
+  AUTO = 1,
+  BANDWIDTH_8MHZ = 2,
+  BANDWIDTH_7MHZ = 4,
+  BANDWIDTH_6MHZ = 8,
+  BANDWIDTH_5MHZ = 16,
+  BANDWIDTH_1_7MHZ = 32,
+  BANDWIDTH_10MHZ = 64,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtCapabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtCapabilities.aidl
new file mode 100644
index 0000000..a0e6ce2
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtCapabilities.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendDvbtCapabilities {
+  int transmissionModeCap;
+  int bandwidthCap;
+  int constellationCap;
+  int coderateCap;
+  int hierarchyCap;
+  int guardIntervalCap;
+  boolean isT2Supported;
+  boolean isMisoSupported;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtCoderate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtCoderate.aidl
new file mode 100644
index 0000000..8bd0489
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtCoderate.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbtCoderate {
+  UNDEFINED = 0,
+  AUTO = 1,
+  CODERATE_1_2 = 2,
+  CODERATE_2_3 = 4,
+  CODERATE_3_4 = 8,
+  CODERATE_5_6 = 16,
+  CODERATE_7_8 = 32,
+  CODERATE_3_5 = 64,
+  CODERATE_4_5 = 128,
+  CODERATE_6_7 = 256,
+  CODERATE_8_9 = 512,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtConstellation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtConstellation.aidl
new file mode 100644
index 0000000..bc40901
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtConstellation.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbtConstellation {
+  UNDEFINED = 0,
+  AUTO = 1,
+  CONSTELLATION_QPSK = 2,
+  CONSTELLATION_16QAM = 4,
+  CONSTELLATION_64QAM = 8,
+  CONSTELLATION_256QAM = 16,
+  CONSTELLATION_QPSK_R = 32,
+  CONSTELLATION_16QAM_R = 64,
+  CONSTELLATION_64QAM_R = 128,
+  CONSTELLATION_256QAM_R = 256,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtGuardInterval.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtGuardInterval.aidl
new file mode 100644
index 0000000..073a77e
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtGuardInterval.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbtGuardInterval {
+  UNDEFINED = 0,
+  AUTO = 1,
+  INTERVAL_1_32 = 2,
+  INTERVAL_1_16 = 4,
+  INTERVAL_1_8 = 8,
+  INTERVAL_1_4 = 16,
+  INTERVAL_1_128 = 32,
+  INTERVAL_19_128 = 64,
+  INTERVAL_19_256 = 128,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtHierarchy.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtHierarchy.aidl
new file mode 100644
index 0000000..9ed5c8c
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtHierarchy.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbtHierarchy {
+  UNDEFINED = 0,
+  AUTO = 1,
+  HIERARCHY_NON_NATIVE = 2,
+  HIERARCHY_1_NATIVE = 4,
+  HIERARCHY_2_NATIVE = 8,
+  HIERARCHY_4_NATIVE = 16,
+  HIERARCHY_NON_INDEPTH = 32,
+  HIERARCHY_1_INDEPTH = 64,
+  HIERARCHY_2_INDEPTH = 128,
+  HIERARCHY_4_INDEPTH = 256,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtPlpMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtPlpMode.aidl
new file mode 100644
index 0000000..c80bc2a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtPlpMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbtPlpMode {
+  UNDEFINED = 0,
+  AUTO = 1,
+  MANUAL = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtSettings.aidl
new file mode 100644
index 0000000..ec1277a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtSettings.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendDvbtSettings {
+  long frequency;
+  long endFrequency;
+  android.hardware.tv.tuner.FrontendSpectralInversion inversion = android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbtTransmissionMode transmissionMode = android.hardware.tv.tuner.FrontendDvbtTransmissionMode.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbtBandwidth bandwidth = android.hardware.tv.tuner.FrontendDvbtBandwidth.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbtConstellation constellation = android.hardware.tv.tuner.FrontendDvbtConstellation.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbtHierarchy hierarchy = android.hardware.tv.tuner.FrontendDvbtHierarchy.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbtCoderate hpCoderate = android.hardware.tv.tuner.FrontendDvbtCoderate.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbtCoderate lpCoderate = android.hardware.tv.tuner.FrontendDvbtCoderate.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbtGuardInterval guardInterval = android.hardware.tv.tuner.FrontendDvbtGuardInterval.UNDEFINED;
+  boolean isHighPriority;
+  android.hardware.tv.tuner.FrontendDvbtStandard standard = android.hardware.tv.tuner.FrontendDvbtStandard.UNDEFINED;
+  boolean isMiso;
+  android.hardware.tv.tuner.FrontendDvbtPlpMode plpMode = android.hardware.tv.tuner.FrontendDvbtPlpMode.UNDEFINED;
+  int plpId;
+  int plpGroupId;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtStandard.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtStandard.aidl
new file mode 100644
index 0000000..c7ba68a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtStandard.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum FrontendDvbtStandard {
+  UNDEFINED = 0,
+  AUTO = 1,
+  T = 2,
+  T2 = 4,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.aidl
new file mode 100644
index 0000000..e3ca2e3
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendDvbtTransmissionMode {
+  UNDEFINED = 0,
+  AUTO = 1,
+  MODE_2K = 2,
+  MODE_8K = 4,
+  MODE_4K = 8,
+  MODE_1K = 16,
+  MODE_16K = 32,
+  MODE_32K = 64,
+  MODE_8K_E = 128,
+  MODE_16K_E = 256,
+  MODE_32K_E = 512,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendEventType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendEventType.aidl
new file mode 100644
index 0000000..443313f
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendEventType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendEventType {
+  LOCKED = 0,
+  NO_SIGNAL = 1,
+  LOST_LOCK = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendGuardInterval.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendGuardInterval.aidl
new file mode 100644
index 0000000..15c738a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendGuardInterval.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendGuardInterval {
+  android.hardware.tv.tuner.FrontendDvbtGuardInterval dvbt = android.hardware.tv.tuner.FrontendDvbtGuardInterval.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbtGuardInterval isdbt;
+  android.hardware.tv.tuner.FrontendDtmbGuardInterval dtmb;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInfo.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInfo.aidl
new file mode 100644
index 0000000..d5bdd58
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInfo.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendInfo {
+  android.hardware.tv.tuner.FrontendType type = android.hardware.tv.tuner.FrontendType.UNDEFINED;
+  long minFrequency;
+  long maxFrequency;
+  int minSymbolRate;
+  int maxSymbolRate;
+  long acquireRange;
+  int exclusiveGroupId;
+  android.hardware.tv.tuner.FrontendStatusType[] statusCaps;
+  android.hardware.tv.tuner.FrontendCapabilities frontendCaps;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInnerFec.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInnerFec.aidl
new file mode 100644
index 0000000..19599a3
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInnerFec.aidl
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="long") @VintfStability
+enum FrontendInnerFec {
+  FEC_UNDEFINED = 0,
+  AUTO = 1,
+  FEC_1_2 = 2,
+  FEC_1_3 = 4,
+  FEC_1_4 = 8,
+  FEC_1_5 = 16,
+  FEC_2_3 = 32,
+  FEC_2_5 = 64,
+  FEC_2_9 = 128,
+  FEC_3_4 = 256,
+  FEC_3_5 = 512,
+  FEC_4_5 = 1024,
+  FEC_4_15 = 2048,
+  FEC_5_6 = 4096,
+  FEC_5_9 = 8192,
+  FEC_6_7 = 16384,
+  FEC_7_8 = 32768,
+  FEC_7_9 = 65536,
+  FEC_7_15 = 131072,
+  FEC_8_9 = 262144,
+  FEC_8_15 = 524288,
+  FEC_9_10 = 1048576,
+  FEC_9_20 = 2097152,
+  FEC_11_15 = 4194304,
+  FEC_11_20 = 8388608,
+  FEC_11_45 = 16777216,
+  FEC_13_18 = 33554432,
+  FEC_13_45 = 67108864,
+  FEC_14_45 = 134217728,
+  FEC_23_36 = 268435456,
+  FEC_25_36 = 536870912,
+  FEC_26_45 = 1073741824,
+  FEC_28_45 = 2147483648,
+  FEC_29_45 = 4294967296,
+  FEC_31_45 = 8589934592,
+  FEC_32_45 = 17179869184,
+  FEC_77_90 = 34359738368,
+  FEC_2_15 = 68719476736,
+  FEC_3_15 = 137438953472,
+  FEC_5_15 = 274877906944,
+  FEC_6_15 = 549755813888,
+  FEC_9_15 = 1099511627776,
+  FEC_10_15 = 2199023255552,
+  FEC_12_15 = 4398046511104,
+  FEC_13_15 = 8796093022208,
+  FEC_18_30 = 17592186044416,
+  FEC_20_30 = 35184372088832,
+  FEC_90_180 = 70368744177664,
+  FEC_96_180 = 140737488355328,
+  FEC_104_180 = 281474976710656,
+  FEC_128_180 = 562949953421312,
+  FEC_132_180 = 1125899906842624,
+  FEC_135_180 = 2251799813685248,
+  FEC_140_180 = 4503599627370496,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInterleaveMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInterleaveMode.aidl
new file mode 100644
index 0000000..ac38731
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendInterleaveMode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendInterleaveMode {
+  android.hardware.tv.tuner.FrontendAtsc3TimeInterleaveMode atsc3 = android.hardware.tv.tuner.FrontendAtsc3TimeInterleaveMode.UNDEFINED;
+  android.hardware.tv.tuner.FrontendCableTimeInterleaveMode dvbc;
+  android.hardware.tv.tuner.FrontendDtmbTimeInterleaveMode dtmb;
+  android.hardware.tv.tuner.FrontendIsdbtTimeInterleaveMode isdbt;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Capabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Capabilities.aidl
new file mode 100644
index 0000000..4be37c2
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Capabilities.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendIsdbs3Capabilities {
+  int modulationCap;
+  int coderateCap;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Coderate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Coderate.aidl
new file mode 100644
index 0000000..1ee7f07
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Coderate.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbs3Coderate {
+  UNDEFINED = 0,
+  AUTO = 1,
+  CODERATE_1_3 = 2,
+  CODERATE_2_5 = 4,
+  CODERATE_1_2 = 8,
+  CODERATE_3_5 = 16,
+  CODERATE_2_3 = 32,
+  CODERATE_3_4 = 64,
+  CODERATE_7_9 = 128,
+  CODERATE_4_5 = 256,
+  CODERATE_5_6 = 512,
+  CODERATE_7_8 = 1024,
+  CODERATE_9_10 = 2048,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Modulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Modulation.aidl
new file mode 100644
index 0000000..3603292
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Modulation.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbs3Modulation {
+  UNDEFINED = 0,
+  AUTO = 1,
+  MOD_BPSK = 2,
+  MOD_QPSK = 4,
+  MOD_8PSK = 8,
+  MOD_16APSK = 16,
+  MOD_32APSK = 32,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Rolloff.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Rolloff.aidl
new file mode 100644
index 0000000..733760c
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Rolloff.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbs3Rolloff {
+  UNDEFINED = 0,
+  ROLLOFF_0_03 = 1,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Settings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Settings.aidl
new file mode 100644
index 0000000..8c491d6
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbs3Settings.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendIsdbs3Settings {
+  long frequency;
+  long endFrequency;
+  int streamId;
+  android.hardware.tv.tuner.FrontendIsdbsStreamIdType streamIdType = android.hardware.tv.tuner.FrontendIsdbsStreamIdType.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbs3Modulation modulation = android.hardware.tv.tuner.FrontendIsdbs3Modulation.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbs3Coderate coderate = android.hardware.tv.tuner.FrontendIsdbs3Coderate.UNDEFINED;
+  int symbolRate;
+  android.hardware.tv.tuner.FrontendIsdbs3Rolloff rolloff = android.hardware.tv.tuner.FrontendIsdbs3Rolloff.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsCapabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsCapabilities.aidl
new file mode 100644
index 0000000..2cb892c
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsCapabilities.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendIsdbsCapabilities {
+  int modulationCap;
+  int coderateCap;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsCoderate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsCoderate.aidl
new file mode 100644
index 0000000..09e9c59
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsCoderate.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbsCoderate {
+  UNDEFINED = 0,
+  AUTO = 1,
+  CODERATE_1_2 = 2,
+  CODERATE_2_3 = 4,
+  CODERATE_3_4 = 8,
+  CODERATE_5_6 = 16,
+  CODERATE_7_8 = 32,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsModulation.aidl
new file mode 100644
index 0000000..7b9bde6
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsModulation.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbsModulation {
+  UNDEFINED = 0,
+  AUTO = 1,
+  MOD_BPSK = 2,
+  MOD_QPSK = 4,
+  MOD_TC8PSK = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsRolloff.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsRolloff.aidl
new file mode 100644
index 0000000..a2ab154
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsRolloff.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbsRolloff {
+  UNDEFINED = 0,
+  ROLLOFF_0_35 = 1,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsSettings.aidl
new file mode 100644
index 0000000..324fb6f
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsSettings.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendIsdbsSettings {
+  long frequency;
+  long endFrequency;
+  int streamId;
+  android.hardware.tv.tuner.FrontendIsdbsStreamIdType streamIdType = android.hardware.tv.tuner.FrontendIsdbsStreamIdType.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbsModulation modulation = android.hardware.tv.tuner.FrontendIsdbsModulation.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbsCoderate coderate = android.hardware.tv.tuner.FrontendIsdbsCoderate.UNDEFINED;
+  int symbolRate;
+  android.hardware.tv.tuner.FrontendIsdbsRolloff rolloff = android.hardware.tv.tuner.FrontendIsdbsRolloff.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsStreamIdType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsStreamIdType.aidl
new file mode 100644
index 0000000..089f611
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbsStreamIdType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbsStreamIdType {
+  STREAM_ID = 0,
+  RELATIVE_STREAM_NUMBER = 1,
+  UNDEFINED = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtBandwidth.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtBandwidth.aidl
new file mode 100644
index 0000000..cd49214
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtBandwidth.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbtBandwidth {
+  UNDEFINED = 0,
+  AUTO = 1,
+  BANDWIDTH_8MHZ = 2,
+  BANDWIDTH_7MHZ = 4,
+  BANDWIDTH_6MHZ = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtCapabilities.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtCapabilities.aidl
new file mode 100644
index 0000000..dbf631b
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtCapabilities.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendIsdbtCapabilities {
+  int modeCap;
+  int bandwidthCap;
+  int modulationCap;
+  int coderateCap;
+  int guardIntervalCap;
+  int timeInterleaveCap;
+  boolean isSegmentAuto;
+  boolean isFullSegment;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtCoderate.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtCoderate.aidl
new file mode 100644
index 0000000..2b747ed
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtCoderate.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbtCoderate {
+  UNDEFINED = 0,
+  AUTO = 1,
+  CODERATE_1_2 = 2,
+  CODERATE_2_3 = 4,
+  CODERATE_3_4 = 8,
+  CODERATE_5_6 = 16,
+  CODERATE_7_8 = 32,
+  CODERATE_3_5 = 64,
+  CODERATE_4_5 = 128,
+  CODERATE_6_7 = 256,
+  CODERATE_8_9 = 512,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtGuardInterval.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtGuardInterval.aidl
new file mode 100644
index 0000000..42a023a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtGuardInterval.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbtGuardInterval {
+  UNDEFINED = 0,
+  AUTO = 1,
+  INTERVAL_1_32 = 2,
+  INTERVAL_1_16 = 4,
+  INTERVAL_1_8 = 8,
+  INTERVAL_1_4 = 16,
+  INTERVAL_1_128 = 32,
+  INTERVAL_19_128 = 64,
+  INTERVAL_19_256 = 128,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtLayerSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtLayerSettings.aidl
new file mode 100644
index 0000000..0055793
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtLayerSettings.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendIsdbtLayerSettings {
+  android.hardware.tv.tuner.FrontendIsdbtModulation modulation = android.hardware.tv.tuner.FrontendIsdbtModulation.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbtCoderate coderate = android.hardware.tv.tuner.FrontendIsdbtCoderate.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbtTimeInterleaveMode timeInterleave = android.hardware.tv.tuner.FrontendIsdbtTimeInterleaveMode.UNDEFINED;
+  int numOfSegment;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtMode.aidl
new file mode 100644
index 0000000..54698ab
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtMode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbtMode {
+  UNDEFINED = 0,
+  AUTO = 1,
+  MODE_1 = 2,
+  MODE_2 = 4,
+  MODE_3 = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtModulation.aidl
new file mode 100644
index 0000000..a31e0cf
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtModulation.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbtModulation {
+  UNDEFINED = 0,
+  AUTO = 1,
+  MOD_DQPSK = 2,
+  MOD_QPSK = 4,
+  MOD_16QAM = 8,
+  MOD_64QAM = 16,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtPartialReceptionFlag.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtPartialReceptionFlag.aidl
new file mode 100644
index 0000000..133887f
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtPartialReceptionFlag.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbtPartialReceptionFlag {
+  UNDEFINED = 0,
+  AUTO = 1,
+  FALSE = 2,
+  TRUE = 4,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtSettings.aidl
new file mode 100644
index 0000000..605bc21
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtSettings.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendIsdbtSettings {
+  long frequency;
+  long endFrequency;
+  android.hardware.tv.tuner.FrontendSpectralInversion inversion = android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbtBandwidth bandwidth = android.hardware.tv.tuner.FrontendIsdbtBandwidth.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbtMode mode = android.hardware.tv.tuner.FrontendIsdbtMode.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbtGuardInterval guardInterval = android.hardware.tv.tuner.FrontendIsdbtGuardInterval.UNDEFINED;
+  int serviceAreaId;
+  android.hardware.tv.tuner.FrontendIsdbtPartialReceptionFlag partialReceptionFlag = android.hardware.tv.tuner.FrontendIsdbtPartialReceptionFlag.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbtLayerSettings[] layerSettings;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.aidl
new file mode 100644
index 0000000..50adde9
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendIsdbtTimeInterleaveMode {
+  UNDEFINED = 0,
+  AUTO = 1,
+  INTERLEAVE_1_0 = 2,
+  INTERLEAVE_1_4 = 4,
+  INTERLEAVE_1_8 = 8,
+  INTERLEAVE_1_16 = 16,
+  INTERLEAVE_2_0 = 32,
+  INTERLEAVE_2_2 = 64,
+  INTERLEAVE_2_4 = 128,
+  INTERLEAVE_2_8 = 256,
+  INTERLEAVE_3_0 = 512,
+  INTERLEAVE_3_1 = 1024,
+  INTERLEAVE_3_2 = 2048,
+  INTERLEAVE_3_4 = 4096,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendModulation.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendModulation.aidl
new file mode 100644
index 0000000..6e396b0
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendModulation.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendModulation {
+  android.hardware.tv.tuner.FrontendDvbcModulation dvbc = android.hardware.tv.tuner.FrontendDvbcModulation.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbsModulation dvbs;
+  android.hardware.tv.tuner.FrontendDvbtConstellation dvbt;
+  android.hardware.tv.tuner.FrontendIsdbsModulation isdbs;
+  android.hardware.tv.tuner.FrontendIsdbs3Modulation isdbs3;
+  android.hardware.tv.tuner.FrontendIsdbtModulation isdbt;
+  android.hardware.tv.tuner.FrontendAtscModulation atsc;
+  android.hardware.tv.tuner.FrontendAtsc3Modulation atsc3;
+  android.hardware.tv.tuner.FrontendDtmbModulation dtmb;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendModulationStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendModulationStatus.aidl
new file mode 100644
index 0000000..723fdd0
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendModulationStatus.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendModulationStatus {
+  android.hardware.tv.tuner.FrontendDvbcModulation dvbc = android.hardware.tv.tuner.FrontendDvbcModulation.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbsModulation dvbs;
+  android.hardware.tv.tuner.FrontendIsdbsModulation isdbs;
+  android.hardware.tv.tuner.FrontendIsdbs3Modulation isdbs3;
+  android.hardware.tv.tuner.FrontendIsdbtModulation isdbt;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendRollOff.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendRollOff.aidl
new file mode 100644
index 0000000..c5f8b8e
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendRollOff.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendRollOff {
+  android.hardware.tv.tuner.FrontendDvbsRolloff dvbs = android.hardware.tv.tuner.FrontendDvbsRolloff.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbsRolloff isdbs;
+  android.hardware.tv.tuner.FrontendIsdbs3Rolloff isdbs3;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanAtsc3PlpInfo.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanAtsc3PlpInfo.aidl
new file mode 100644
index 0000000..56ef3e3
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanAtsc3PlpInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendScanAtsc3PlpInfo {
+  int plpId;
+  boolean bLlsFlag;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessage.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessage.aidl
new file mode 100644
index 0000000..e763cfb
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessage.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendScanMessage {
+  boolean isLocked;
+  boolean isEnd;
+  int progressPercent;
+  long[] frequencies;
+  int[] symbolRates;
+  android.hardware.tv.tuner.FrontendDvbtHierarchy hierarchy;
+  android.hardware.tv.tuner.FrontendAnalogType analogType;
+  int[] plpIds;
+  int[] groupIds;
+  int[] inputStreamIds;
+  android.hardware.tv.tuner.FrontendScanMessageStandard std;
+  android.hardware.tv.tuner.FrontendScanAtsc3PlpInfo[] atsc3PlpInfos;
+  android.hardware.tv.tuner.FrontendModulation modulation;
+  android.hardware.tv.tuner.FrontendDvbcAnnex annex;
+  boolean isHighPriority;
+  int[] dvbtCellIds;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessageStandard.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessageStandard.aidl
new file mode 100644
index 0000000..e163fc6
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessageStandard.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendScanMessageStandard {
+  android.hardware.tv.tuner.FrontendDvbsStandard sStd = android.hardware.tv.tuner.FrontendDvbsStandard.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbtStandard tStd;
+  android.hardware.tv.tuner.FrontendAnalogSifStandard sifStd;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessageType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessageType.aidl
new file mode 100644
index 0000000..6976ecd
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanMessageType.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendScanMessageType {
+  LOCKED = 0,
+  END = 1,
+  PROGRESS_PERCENT = 2,
+  FREQUENCY = 3,
+  SYMBOL_RATE = 4,
+  HIERARCHY = 5,
+  ANALOG_TYPE = 6,
+  PLP_IDS = 7,
+  GROUP_IDS = 8,
+  INPUT_STREAM_IDS = 9,
+  STANDARD = 10,
+  ATSC3_PLP_INFO = 11,
+  MODULATION = 12,
+  DVBC_ANNEX = 13,
+  HIGH_PRIORITY = 14,
+  DVBT_CELL_IDS = 15,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanType.aidl
new file mode 100644
index 0000000..ed42d0a
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendScanType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendScanType {
+  SCAN_UNDEFINED = 0,
+  SCAN_AUTO = 1,
+  SCAN_BLIND = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendSettings.aidl
new file mode 100644
index 0000000..7eae9df
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendSettings.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendSettings {
+  android.hardware.tv.tuner.FrontendAnalogSettings analog;
+  android.hardware.tv.tuner.FrontendAtscSettings atsc;
+  android.hardware.tv.tuner.FrontendAtsc3Settings atsc3;
+  android.hardware.tv.tuner.FrontendDvbsSettings dvbs;
+  android.hardware.tv.tuner.FrontendDvbcSettings dvbc;
+  android.hardware.tv.tuner.FrontendDvbtSettings dvbt;
+  android.hardware.tv.tuner.FrontendIsdbsSettings isdbs;
+  android.hardware.tv.tuner.FrontendIsdbs3Settings isdbs3;
+  android.hardware.tv.tuner.FrontendIsdbtSettings isdbt;
+  android.hardware.tv.tuner.FrontendDtmbSettings dtmb;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendSpectralInversion.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendSpectralInversion.aidl
new file mode 100644
index 0000000..ff11bb8
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendSpectralInversion.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendSpectralInversion {
+  UNDEFINED = 0,
+  NORMAL = 1,
+  INVERTED = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl
new file mode 100644
index 0000000..fc0efc9
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendStatus {
+  boolean isDemodLocked;
+  int snr;
+  int ber;
+  int per;
+  int preBer;
+  int signalQuality;
+  int signalStrength;
+  int symbolRate;
+  android.hardware.tv.tuner.FrontendInnerFec innerFec;
+  android.hardware.tv.tuner.FrontendModulationStatus modulationStatus;
+  android.hardware.tv.tuner.FrontendSpectralInversion inversion;
+  android.hardware.tv.tuner.LnbVoltage lnbVoltage;
+  int plpId;
+  boolean isEWBS;
+  int agc;
+  boolean isLnaOn;
+  boolean[] isLayerError;
+  int mer;
+  long freqOffset;
+  android.hardware.tv.tuner.FrontendDvbtHierarchy hierarchy;
+  boolean isRfLocked;
+  android.hardware.tv.tuner.FrontendStatusAtsc3PlpInfo[] plpInfo;
+  android.hardware.tv.tuner.FrontendModulation[] modulations;
+  int[] bers;
+  android.hardware.tv.tuner.FrontendInnerFec[] codeRates;
+  android.hardware.tv.tuner.FrontendBandwidth bandwidth;
+  android.hardware.tv.tuner.FrontendGuardInterval interval;
+  android.hardware.tv.tuner.FrontendTransmissionMode transmissionMode;
+  int uec;
+  int systemId;
+  android.hardware.tv.tuner.FrontendInterleaveMode[] interleaving;
+  int[] isdbtSegment;
+  int[] tsDataRate;
+  android.hardware.tv.tuner.FrontendRollOff rollOff;
+  boolean isMiso;
+  boolean isLinear;
+  boolean isShortFrames;
+  android.hardware.tv.tuner.FrontendIsdbtMode isdbtMode;
+  android.hardware.tv.tuner.FrontendIsdbtPartialReceptionFlag partialReceptionFlag;
+  int[] streamIdList;
+  int[] dvbtCellIds;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusAtsc3PlpInfo.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusAtsc3PlpInfo.aidl
new file mode 100644
index 0000000..8f65925
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusAtsc3PlpInfo.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable FrontendStatusAtsc3PlpInfo {
+  int plpId;
+  boolean isLocked;
+  int uec;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl
new file mode 100644
index 0000000..2cc62d5
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendStatusType {
+  DEMOD_LOCK = 0,
+  SNR = 1,
+  BER = 2,
+  PER = 3,
+  PRE_BER = 4,
+  SIGNAL_QUALITY = 5,
+  SIGNAL_STRENGTH = 6,
+  SYMBOL_RATE = 7,
+  FEC = 8,
+  MODULATION = 9,
+  SPECTRAL = 10,
+  LNB_VOLTAGE = 11,
+  PLP_ID = 12,
+  EWBS = 13,
+  AGC = 14,
+  LNA = 15,
+  LAYER_ERROR = 16,
+  MER = 17,
+  FREQ_OFFSET = 18,
+  HIERARCHY = 19,
+  RF_LOCK = 20,
+  ATSC3_PLP_INFO = 21,
+  MODULATIONS = 22,
+  BERS = 23,
+  CODERATES = 24,
+  BANDWIDTH = 25,
+  GUARD_INTERVAL = 26,
+  TRANSMISSION_MODE = 27,
+  UEC = 28,
+  T2_SYSTEM_ID = 29,
+  INTERLEAVINGS = 30,
+  ISDBT_SEGMENTS = 31,
+  TS_DATA_RATES = 32,
+  ROLL_OFF = 33,
+  IS_MISO = 34,
+  IS_LINEAR = 35,
+  IS_SHORT_FRAMES = 36,
+  ISDBT_MODE = 37,
+  ISDBT_PARTIAL_RECEPTION_FLAG = 38,
+  STREAM_ID_LIST = 39,
+  DVBT_CELL_IDS = 40,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendTransmissionMode.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendTransmissionMode.aidl
new file mode 100644
index 0000000..72c3641
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendTransmissionMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+union FrontendTransmissionMode {
+  android.hardware.tv.tuner.FrontendDvbtTransmissionMode dvbt = android.hardware.tv.tuner.FrontendDvbtTransmissionMode.UNDEFINED;
+  android.hardware.tv.tuner.FrontendIsdbtMode isdbt;
+  android.hardware.tv.tuner.FrontendDtmbTransmissionMode dtmb;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendType.aidl
new file mode 100644
index 0000000..99a120b
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendType.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum FrontendType {
+  UNDEFINED = 0,
+  ANALOG = 1,
+  ATSC = 2,
+  ATSC3 = 3,
+  DVBC = 4,
+  DVBS = 5,
+  DVBT = 6,
+  ISDBS = 7,
+  ISDBS3 = 8,
+  ISDBT = 9,
+  DTMB = 10,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDemux.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDemux.aidl
new file mode 100644
index 0000000..59ec92b
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDemux.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+interface IDemux {
+  void setFrontendDataSource(in int frontendId);
+  android.hardware.tv.tuner.IFilter openFilter(in android.hardware.tv.tuner.DemuxFilterType type, in int bufferSize, in android.hardware.tv.tuner.IFilterCallback cb);
+  android.hardware.tv.tuner.ITimeFilter openTimeFilter();
+  int getAvSyncHwId(in android.hardware.tv.tuner.IFilter filter);
+  long getAvSyncTime(in int avSyncHwId);
+  void close();
+  android.hardware.tv.tuner.IDvr openDvr(in android.hardware.tv.tuner.DvrType type, in int bufferSize, in android.hardware.tv.tuner.IDvrCallback cb);
+  void connectCiCam(in int ciCamId);
+  void disconnectCiCam();
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDescrambler.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDescrambler.aidl
new file mode 100644
index 0000000..3cf3c04
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDescrambler.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+interface IDescrambler {
+  void setDemuxSource(in int demuxId);
+  void setKeyToken(in byte[] keyToken);
+  void addPid(in android.hardware.tv.tuner.DemuxPid pid, in android.hardware.tv.tuner.IFilter optionalSourceFilter);
+  void removePid(in android.hardware.tv.tuner.DemuxPid pid, in android.hardware.tv.tuner.IFilter optionalSourceFilter);
+  void close();
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvr.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvr.aidl
new file mode 100644
index 0000000..450cd79
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvr.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+interface IDvr {
+  void getQueueDesc(out android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> queue);
+  void configure(in android.hardware.tv.tuner.DvrSettings settings);
+  void attachFilter(in android.hardware.tv.tuner.IFilter filter);
+  void detachFilter(in android.hardware.tv.tuner.IFilter filter);
+  void start();
+  void stop();
+  void flush();
+  void close();
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvrCallback.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvrCallback.aidl
new file mode 100644
index 0000000..13c8644
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvrCallback.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+interface IDvrCallback {
+  oneway void onPlaybackStatus(in android.hardware.tv.tuner.PlaybackStatus status);
+  oneway void onRecordStatus(in android.hardware.tv.tuner.RecordStatus status);
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFilter.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFilter.aidl
new file mode 100644
index 0000000..32d9d64
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFilter.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+interface IFilter {
+  void getQueueDesc(out android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> queue);
+  void close();
+  void configure(in android.hardware.tv.tuner.DemuxFilterSettings settings);
+  void configureAvStreamType(in android.hardware.tv.tuner.AvStreamType avStreamType);
+  void configureIpCid(in int ipCid);
+  void configureMonitorEvent(in int monitorEventTypes);
+  void start();
+  void stop();
+  void flush();
+  long getAvSharedHandle(out android.hardware.common.NativeHandle avMemory);
+  int getId();
+  long getId64Bit();
+  void releaseAvHandle(in android.hardware.common.NativeHandle avMemory, in long avDataId);
+  void setDataSource(in android.hardware.tv.tuner.IFilter filter);
+  void setDelayHint(in android.hardware.tv.tuner.FilterDelayHint hint);
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFilterCallback.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFilterCallback.aidl
new file mode 100644
index 0000000..d8bedba
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFilterCallback.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+interface IFilterCallback {
+  oneway void onFilterEvent(in android.hardware.tv.tuner.DemuxFilterEvent[] events);
+  oneway void onFilterStatus(in android.hardware.tv.tuner.DemuxFilterStatus status);
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontend.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontend.aidl
new file mode 100644
index 0000000..e7aa070
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontend.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+interface IFrontend {
+  void setCallback(in android.hardware.tv.tuner.IFrontendCallback callback);
+  void tune(in android.hardware.tv.tuner.FrontendSettings settings);
+  void stopTune();
+  void close();
+  void scan(in android.hardware.tv.tuner.FrontendSettings settings, in android.hardware.tv.tuner.FrontendScanType type);
+  void stopScan();
+  android.hardware.tv.tuner.FrontendStatus[] getStatus(in android.hardware.tv.tuner.FrontendStatusType[] statusTypes);
+  void setLnb(in int lnbId);
+  int linkCiCam(in int ciCamId);
+  void unlinkCiCam(in int ciCamId);
+  String getHardwareInfo();
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontendCallback.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontendCallback.aidl
new file mode 100644
index 0000000..c22d280
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontendCallback.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+interface IFrontendCallback {
+  oneway void onEvent(in android.hardware.tv.tuner.FrontendEventType frontendEventType);
+  oneway void onScanMessage(in android.hardware.tv.tuner.FrontendScanMessageType type, in android.hardware.tv.tuner.FrontendScanMessage message);
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ILnb.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ILnb.aidl
new file mode 100644
index 0000000..c3fdd87
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ILnb.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+interface ILnb {
+  void setCallback(in android.hardware.tv.tuner.ILnbCallback callback);
+  void setVoltage(in android.hardware.tv.tuner.LnbVoltage voltage);
+  void setTone(in android.hardware.tv.tuner.LnbTone tone);
+  void setSatellitePosition(in android.hardware.tv.tuner.LnbPosition position);
+  void sendDiseqcMessage(in byte[] diseqcMessage);
+  void close();
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ILnbCallback.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ILnbCallback.aidl
new file mode 100644
index 0000000..42e84da
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ILnbCallback.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+interface ILnbCallback {
+  oneway void onDiseqcMessage(in byte[] diseqcMessage);
+  oneway void onEvent(in android.hardware.tv.tuner.LnbEventType lnbEventType);
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITimeFilter.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITimeFilter.aidl
new file mode 100644
index 0000000..838eeba
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITimeFilter.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+interface ITimeFilter {
+  void setTimeStamp(in long timeStamp);
+  void clearTimeStamp();
+  long getTimeStamp();
+  long getSourceTime();
+  void close();
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl
new file mode 100644
index 0000000..decf5b1
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@SuppressWarnings(value={"out-array"}) @VintfStability
+interface ITuner {
+  int[] getFrontendIds();
+  android.hardware.tv.tuner.IFrontend openFrontendById(in int frontendId);
+  android.hardware.tv.tuner.IDemux openDemux(out int[] demuxId);
+  android.hardware.tv.tuner.DemuxCapabilities getDemuxCaps();
+  android.hardware.tv.tuner.IDescrambler openDescrambler();
+  android.hardware.tv.tuner.FrontendInfo getFrontendInfo(in int frontendId);
+  int[] getLnbIds();
+  android.hardware.tv.tuner.ILnb openLnbById(in int lnbId);
+  android.hardware.tv.tuner.ILnb openLnbByName(in String lnbName, out int[] lnbId);
+  void setLna(in boolean bEnable);
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbEventType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbEventType.aidl
new file mode 100644
index 0000000..e6e2b05
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbEventType.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum LnbEventType {
+  DISEQC_RX_OVERFLOW = 0,
+  DISEQC_RX_TIMEOUT = 1,
+  DISEQC_RX_PARITY_ERROR = 2,
+  LNB_OVERLOAD = 3,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbPosition.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbPosition.aidl
new file mode 100644
index 0000000..5fc4d15
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbPosition.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum LnbPosition {
+  UNDEFINED = 0,
+  POSITION_A = 1,
+  POSITION_B = 2,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbTone.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbTone.aidl
new file mode 100644
index 0000000..3217de9
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbTone.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum LnbTone {
+  NONE = 0,
+  CONTINUOUS = 1,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbVoltage.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbVoltage.aidl
new file mode 100644
index 0000000..034c7e6
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/LnbVoltage.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum LnbVoltage {
+  NONE = 0,
+  VOLTAGE_5V = 1,
+  VOLTAGE_11V = 2,
+  VOLTAGE_12V = 3,
+  VOLTAGE_13V = 4,
+  VOLTAGE_14V = 5,
+  VOLTAGE_15V = 6,
+  VOLTAGE_18V = 7,
+  VOLTAGE_19V = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/PlaybackSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/PlaybackSettings.aidl
new file mode 100644
index 0000000..e0dd5db
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/PlaybackSettings.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable PlaybackSettings {
+  int statusMask;
+  long lowThreshold;
+  long highThreshold;
+  android.hardware.tv.tuner.DataFormat dataFormat = android.hardware.tv.tuner.DataFormat.UNDEFINED;
+  long packetSize;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/PlaybackStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/PlaybackStatus.aidl
new file mode 100644
index 0000000..850b737
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/PlaybackStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum PlaybackStatus {
+  SPACE_EMPTY = 1,
+  SPACE_ALMOST_EMPTY = 2,
+  SPACE_ALMOST_FULL = 4,
+  SPACE_FULL = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/RecordSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/RecordSettings.aidl
new file mode 100644
index 0000000..de693cd
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/RecordSettings.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@VintfStability
+parcelable RecordSettings {
+  int statusMask;
+  long lowThreshold;
+  long highThreshold;
+  android.hardware.tv.tuner.DataFormat dataFormat = android.hardware.tv.tuner.DataFormat.UNDEFINED;
+  long packetSize;
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/RecordStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/RecordStatus.aidl
new file mode 100644
index 0000000..48bf9ec
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/RecordStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="byte") @VintfStability
+enum RecordStatus {
+  DATA_READY = 1,
+  LOW_WATER = 2,
+  HIGH_WATER = 4,
+  OVERFLOW = 8,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Result.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Result.aidl
new file mode 100644
index 0000000..4e22f67
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/Result.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum Result {
+  SUCCESS = 0,
+  UNAVAILABLE = 1,
+  NOT_INITIALIZED = 2,
+  INVALID_STATE = 3,
+  INVALID_ARGUMENT = 4,
+  OUT_OF_MEMORY = 5,
+  UNKNOWN_ERROR = 6,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ScramblingStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ScramblingStatus.aidl
new file mode 100644
index 0000000..656fe20
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ScramblingStatus.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum ScramblingStatus {
+  UNKNOWN = 1,
+  NOT_SCRAMBLED = 2,
+  SCRAMBLED = 4,
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/VideoStreamType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/VideoStreamType.aidl
new file mode 100644
index 0000000..9dfd686
--- /dev/null
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/VideoStreamType.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.tuner;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum VideoStreamType {
+  UNDEFINED = 0,
+  RESERVED = 1,
+  MPEG1 = 2,
+  MPEG2 = 3,
+  MPEG4P2 = 4,
+  AVC = 5,
+  HEVC = 6,
+  VC1 = 7,
+  VP8 = 8,
+  VP9 = 9,
+  AV1 = 10,
+  AVS = 11,
+  AVS2 = 12,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/AudioExtraMetaData.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/AudioExtraMetaData.aidl
new file mode 100644
index 0000000..ea2ef4f
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/AudioExtraMetaData.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Extra Meta Data from AD (Audio Descriptor) according to
+ * ETSI TS 101 154 V2.1.1.
+ * @hide
+ */
+@VintfStability
+parcelable AudioExtraMetaData {
+    byte adFade;
+
+    byte adPan;
+
+    char  versionTextTag;
+
+    byte adGainCenter;
+
+    byte adGainFront;
+
+    byte adGainSurround;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/AudioStreamType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/AudioStreamType.aidl
new file mode 100644
index 0000000..9e9a8cf
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/AudioStreamType.aidl
@@ -0,0 +1,122 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Audio stream coding format.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum AudioStreamType {
+    UNDEFINED,
+
+    /*
+     * Uncompressed Audio
+     */
+    PCM,
+
+    /*
+     * MPEG Audio Layer III versions
+     */
+    MP3,
+
+    /*
+     * ISO/IEC 11172 Audio
+     */
+    MPEG1,
+
+    /*
+     * ISO/IEC 13818-3
+     */
+    MPEG2,
+
+    /*
+     * ISO/IEC 23008-3 (MPEG-H Part 3)
+     */
+    MPEGH,
+
+    /*
+     * ISO/IEC 14496-3
+     */
+    AAC,
+
+    /*
+     * Dolby Digital
+     */
+    AC3,
+
+    /*
+     * Dolby Digital Plus
+     */
+    EAC3,
+
+    /*
+     * Dolby AC-4
+     */
+    AC4,
+
+    /*
+     * Basic DTS
+     */
+    DTS,
+
+    /*
+     * High Resolution DTS
+     */
+    DTS_HD,
+
+    /*
+     * Windows Media Audio
+     */
+    WMA,
+
+    /*
+     * Opus Interactive Audio Codec
+     */
+    OPUS,
+
+    /*
+     * VORBIS Interactive Audio Codec
+     */
+    VORBIS,
+
+    /*
+     * SJ/T 11368-2006
+     */
+    DRA,
+
+    /*
+     * AAC with ADTS (Audio Data Transport Format).
+     */
+    AAC_ADTS,
+
+    /*
+     * AAC with ADTS with LATM (Low-overhead MPEG-4 Audio Transport Multiplex).
+     */
+    AAC_LATM,
+
+    /*
+     * High-Efficiency AAC (HE-AAC) with ADTS (Audio Data Transport Format).
+     */
+    AAC_HE_ADTS,
+
+    /*
+     * High-Efficiency AAC (HE-AAC) with LATM (Low-overhead MPEG-4 Audio Transport Multiplex).
+     */
+    AAC_HE_LATM,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/AvStreamType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/AvStreamType.aidl
new file mode 100644
index 0000000..684dfb9
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/AvStreamType.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.AudioStreamType;
+import android.hardware.tv.tuner.VideoStreamType;
+
+/**
+ * Stream type for A/V filter.
+ * @hide
+ */
+@VintfStability
+union AvStreamType {
+    VideoStreamType video = VideoStreamType.UNDEFINED;
+
+    AudioStreamType audio;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/Constant.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/Constant.aidl
new file mode 100644
index 0000000..0751d26
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/Constant.aidl
@@ -0,0 +1,91 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum Constant {
+    /**
+     * An invalid packet ID in transport stream according to ISO/IEC 13818-1.
+     */
+    INVALID_TS_PID = 0xFFFF,
+
+    /**
+     * An invalid Stream ID.
+     */
+    INVALID_STREAM_ID = 0xFFFF,
+
+    /**
+     * An invalid Filter ID.
+     */
+    INVALID_FILTER_ID = 0xFFFFFFFF,
+
+    /**
+     * An invalid AV sync hardware ID.
+     */
+    INVALID_AV_SYNC_ID = 0xFFFFFFFF,
+
+    /**
+     * An invalid mpuSequenceNumber.
+     */
+    INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = 0xFFFFFFFF,
+
+    /**
+     * An invalid first macroblock address.
+     */
+    INVALID_FIRST_MACROBLOCK_IN_SLICE = 0xFFFFFFFF,
+
+    /**
+     * An invalid frenquency that can be used as the default value of the frontend setting.
+     */
+    INVALID_FRONTEND_SETTING_FREQUENCY = 0xFFFFFFFF,
+
+    /**
+     * An invalid context id that can be used as the default value of the unconfigured id. It can
+     * be used to reset the configured ip context id.
+     */
+    INVALID_IP_FILTER_CONTEXT_ID = 0xFFFFFFFF,
+
+    /**
+     * An invalid local transport stream id used as the return value on a failed operation of
+     * IFrontend.linkCiCam.
+     */
+    INVALID_LTS_ID = 0xFFFFFFFF,
+
+    /**
+     * An invalid frontend ID.
+     */
+    INVALID_FRONTEND_ID = 0xFFFFFFFF,
+
+    /**
+     * An invalid LNB ID.
+     */
+    INVALID_LNB_ID = 0xFFFFFFFF,
+
+    /**
+     * An invalid key token. It is used to remove the current key from the descrambler.
+     */
+    INVALID_KEYTOKEN = 0x00,
+
+     /**
+     * An invalid section filter version number.
+     */
+    INVALID_TABINFO_VERSION = 0xFFFFFFFF,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/Constant64Bit.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/Constant64Bit.aidl
new file mode 100644
index 0000000..31a7f5b
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/Constant64Bit.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * @hide
+ */
+@VintfStability
+@Backing(type="long")
+enum Constant64Bit {
+    /**
+     * An invalid 64-bit Filter ID.
+     */
+    INVALID_FILTER_ID_64BIT = 0xFFFFFFFFFFFFFFFF,
+
+    /**
+     * An invalid 64-bit AV sync hardware ID.
+     */
+    INVALID_AV_SYNC_ID_64BIT = 0xFFFFFFFFFFFFFFFF,
+
+    /**
+     * An invalid pts.
+     */
+    INVALID_PRESENTATION_TIME_STAMP = 0xFFFFFFFFFFFFFFFF,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DataFormat.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DataFormat.aidl
new file mode 100644
index 0000000..bbc811d
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DataFormat.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * A data format in demux's output or input according to ISO/IEC 13818-1.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DataFormat {
+    /**
+     * Data is Transport Stream.
+     */
+    TS,
+
+    /**
+     * Data is Packetized Elementary Stream.
+     */
+    PES,
+
+    /**
+     * Data is Elementary Stream.
+     */
+    ES,
+
+    /**
+     * Data is TLV (type-length-value) Stream for JP SHV
+     */
+    SHV_TLV,
+
+    /**
+     * Data format is undefined.
+     */
+    UNDEFINED,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpFilterSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpFilterSettings.aidl
new file mode 100644
index 0000000..95bcf65
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpFilterSettings.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxAlpFilterSettingsFilterSettings;
+import android.hardware.tv.tuner.DemuxAlpLengthType;
+
+/**
+ * Filter Settings for a ALP filter.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxAlpFilterSettings {
+    /**
+     * Packet type according to A/330 ATSC3.0.
+     * 0: IPv4 packet
+     * 2: Compressed IP packet
+     * 4: Link layer signaling packet
+     * 6: Packet Type Extension
+     * 8: MPEG-2 Transport Stream
+     */
+    int packetType;
+
+    DemuxAlpLengthType lengthType = DemuxAlpLengthType.UNDEFINED;
+
+    DemuxAlpFilterSettingsFilterSettings filterSettings;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpFilterSettingsFilterSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpFilterSettingsFilterSettings.aidl
new file mode 100644
index 0000000..9ab967e
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpFilterSettingsFilterSettings.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterSectionSettings;
+
+/**
+ * @hide
+ */
+@VintfStability
+union DemuxAlpFilterSettingsFilterSettings {
+    /**
+     * Not additional parameters. it's used by PTP, PAYLOAD_THROUGH subtype
+     * filters.
+     */
+    boolean noinit;
+
+    DemuxFilterSectionSettings section;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpFilterType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpFilterType.aidl
new file mode 100644
index 0000000..fc36b93
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpFilterType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * ALP Filter Type according to A/330 ATSC3.0.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxAlpFilterType {
+    UNDEFINED,
+    /**
+     * A filter to filter signaling data out from input stream, and queue the
+     * data to the filter's FMQ (Fast Message Queue).
+     */
+    SECTION,
+
+    /**
+     * A filter to set PTP (Precision Time Protocol) channel from input stream.
+     */
+    PTP,
+
+    /**
+     * A filter to strip out ALP message header and be a data source of another
+     * filter.
+     */
+    PAYLOAD_THROUGH,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpLengthType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpLengthType.aidl
new file mode 100644
index 0000000..7d697ad
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxAlpLengthType.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * ALP Length Type
+ * @hide
+ */
+@VintfStability
+@Backing(type="byte")
+enum DemuxAlpLengthType {
+    UNDEFINED = 0,
+
+    /**
+     * Length does NOT include additional header. Used in US region.
+     */
+    WITHOUT_ADDITIONAL_HEADER,
+
+    /**
+     * Length includes additional header. Used in Korea region.
+     */
+    WITH_ADDITIONAL_HEADER,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxCapabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxCapabilities.aidl
new file mode 100644
index 0000000..6d61c97
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxCapabilities.aidl
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Capabilities for Demux.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxCapabilities {
+    /**
+     * The number of Demux to be supported.
+     */
+    int numDemux;
+
+    /**
+     * The number of record to be supported.
+     */
+    int numRecord;
+
+    /**
+     * The number of playback to be supported.
+     */
+    int numPlayback;
+
+    /**
+     * The number of TS Filter to be supported.
+     */
+    int numTsFilter;
+
+    /**
+     * The number of Section Filter to be supported.
+     */
+    int numSectionFilter;
+
+    /**
+     * The number of Audio Filter to be supported.
+     */
+    int numAudioFilter;
+
+    /**
+     * The number of Video Filter to be supported.
+     */
+    int numVideoFilter;
+
+    /**
+     * The number of PES Filter to be supported.
+     */
+    int numPesFilter;
+
+    /**
+     * The number of PCR Filter to be supported.
+     */
+    int numPcrFilter;
+
+    /**
+     * The maximum number of bytes is supported in the mask of Section Filter.
+     */
+    long numBytesInSectionFilter;
+
+    /**
+     * Filter Main Types defined by DemuxFilterMainType. The DemuxFilterMainTypes
+     * is set by bitwise OR.
+     */
+    int filterCaps;
+
+    /**
+     * The array has same elements as DemuxFilterMainType. linkCaps[i] presents
+     * filter's capability as source for the ith type in DemuxFilterMainType.
+     * The jth bit of linkCaps[i] is 1 if the output of ith type filter can be
+     * data source for the filter type j.
+     */
+    int[] linkCaps;
+
+    /**
+     * True if Time Filter to be supported.
+     */
+    boolean bTimeFilter;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterAvSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterAvSettings.aidl
new file mode 100644
index 0000000..fe4db5b
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterAvSettings.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Filter Settings for a Video and Audio.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterAvSettings {
+    /**
+     * true if the filter output goes to decoder directly in pass through mode.
+     */
+    boolean isPassthrough;
+
+    /**
+     * true if the avMemory should be allocated from secure area.
+     */
+    boolean isSecureMemory;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl
new file mode 100644
index 0000000..b9df5a0
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Filter Event for Download data.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterDownloadEvent {
+    /**
+     * ID of object/module in the carousel
+     */
+    int itemId;
+
+    /**
+     * Uniquely identify data content within the same Package ID (PID).
+     */
+    int downloadId;
+
+    /**
+     * MPU sequence number of filtered data (only for MMTP)
+     */
+    int mpuSequenceNumber;
+
+    int itemFragmentIndex;
+
+    int lastItemFragmentIndex;
+
+    /**
+     * Data size in bytes of filtered data
+     */
+    int dataLength;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl
new file mode 100644
index 0000000..1188b03
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Filter Settings for a Download.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterDownloadSettings {
+    /**
+     * Whether download ID should be used.
+     */
+    boolean useDownloadId;
+
+    /**
+     * Download ID (also known as the carousel ID) is carried in the PMT in
+     * ISO/IEC 13818-1 for the service containing the object carousel.
+     */
+    int downloadId;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterEvent.aidl
new file mode 100644
index 0000000..8de80e0
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterEvent.aidl
@@ -0,0 +1,62 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterDownloadEvent;
+import android.hardware.tv.tuner.DemuxFilterIpPayloadEvent;
+import android.hardware.tv.tuner.DemuxFilterMediaEvent;
+import android.hardware.tv.tuner.DemuxFilterMmtpRecordEvent;
+import android.hardware.tv.tuner.DemuxFilterMonitorEvent;
+import android.hardware.tv.tuner.DemuxFilterPesEvent;
+import android.hardware.tv.tuner.DemuxFilterSectionEvent;
+import android.hardware.tv.tuner.DemuxFilterTemiEvent;
+import android.hardware.tv.tuner.DemuxFilterTsRecordEvent;
+
+/**
+ * Filter Event.
+ * @hide
+ */
+@VintfStability
+union DemuxFilterEvent {
+    DemuxFilterSectionEvent section;
+
+    DemuxFilterMediaEvent media;
+
+    DemuxFilterPesEvent pes;
+
+    DemuxFilterTsRecordEvent tsRecord;
+
+    DemuxFilterMmtpRecordEvent mmtpRecord;
+
+    DemuxFilterDownloadEvent download;
+
+    DemuxFilterIpPayloadEvent ipPayload;
+
+    DemuxFilterTemiEvent temi;
+
+    DemuxFilterMonitorEvent monitorEvent;
+
+    /**
+     * An unique ID to mark the start point of receiving the valid filter events after
+     * reconfiguring the filter. It must be sent at least once in the first event after the
+     * filter is restarted. 0 is reserved for the newly opened filter's first start, which is
+     * optional for HAL to send.
+     *
+     * When sending starId, DemuxFilterEvent.events should only contain one startId event.
+     */
+    int startId;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterIpPayloadEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterIpPayloadEvent.aidl
new file mode 100644
index 0000000..4d6c6e2
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterIpPayloadEvent.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Filter Event for IP payload data.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterIpPayloadEvent {
+    /**
+     * Data size in bytes of IP data
+     */
+    int dataLength;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMainType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMainType.aidl
new file mode 100644
index 0000000..663bdfb
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMainType.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Filter Main Type specifies the protocol that the filter use to extract data
+ * from input stream.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxFilterMainType {
+    UNDEFINED = 0,
+
+    /**
+     * Transport Stream according to ISO/IEC 13818-1.
+     */
+    TS = 1 << 0,
+
+    /**
+     * MPEG Media Transport Protocol according to ISO/IEC 23008-1.
+     */
+    MMTP = 1 << 1,
+
+    /**
+     * Internet Protocol.
+     */
+    IP = 1 << 2,
+
+    /**
+     * Type Length Value according to ITU-R BT.1869.
+     */
+    TLV = 1 << 3,
+
+    /**
+     * ATSC Link-Layer Protocol according to A/330 ATSC3.0.
+     */
+    ALP = 1 << 4,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
new file mode 100644
index 0000000..32f0cb2
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
@@ -0,0 +1,94 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.common.NativeHandle;
+
+import android.hardware.tv.tuner.DemuxFilterMediaEventExtraMetaData;
+import android.hardware.tv.tuner.DemuxFilterScIndexMask;
+
+/**
+ * Filter Event for Audio or Video Filter.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterMediaEvent {
+    int streamId;
+
+    /**
+     * true if PTS is present in PES header.
+     */
+    boolean isPtsPresent;
+
+    /**
+     * Presentation Time Stamp for audio or video frame. It based on 90KHz has
+     * the same format as PTS (Presentation Time Stamp).
+     */
+    long pts;
+
+    /**
+     * true if DTS is present in the PES header.
+     */
+    boolean isDtsPresent;
+
+    /**
+     * Decode TimeStamp for audio or video frame.
+     */
+    long dts;
+
+    /**
+     * Data size in bytes of audio or video frame
+     */
+    long dataLength;
+
+    /**
+     *  The offset in the memory block which is shared among multiple
+     *  MediaEvents.
+     */
+    long offset;
+
+    /**
+     * A handle associated to the memory where audio or video data stays.
+     */
+    NativeHandle avMemory;
+
+    /**
+     * True if the avMemory is in secure area, and isn't mappable.
+     */
+    boolean isSecureMemory;
+
+    /**
+     * An Id is used by HAL to provide additional information for AV data.
+     * For secure audio, it's the audio handle used by Audio Track.
+     */
+    long avDataId;
+
+    /**
+     * MPU sequence number of filtered data (only for MMTP)
+     */
+    int mpuSequenceNumber;
+
+    boolean isPesPrivateData;
+
+    DemuxFilterMediaEventExtraMetaData extraMetaData;
+
+    /**
+     * DemuxFilterScIndexMask for the key frame info. It's optional to hardware which can only
+     * access unit framing at decode stage.
+     */
+    DemuxFilterScIndexMask scIndexMask;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEventExtraMetaData.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEventExtraMetaData.aidl
new file mode 100644
index 0000000..f01952b
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEventExtraMetaData.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.AudioExtraMetaData;
+
+/**
+ * Extra Meta Data for DemuxFilterMediaEvent.
+ * @hide
+ */
+@VintfStability
+union DemuxFilterMediaEventExtraMetaData {
+    /**
+     * Not additional parameters. it's used for video.
+     */
+    boolean noinit;
+
+    AudioExtraMetaData audio;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMmtpRecordEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMmtpRecordEvent.aidl
new file mode 100644
index 0000000..39083a9
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMmtpRecordEvent.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Filter Event for MMTP Record data.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterMmtpRecordEvent {
+    /**
+     * Indexes defined by DemuxScHevcIndex.
+     */
+    int scHevcIndexMask;
+
+    /**
+     * Byte number from beginning of the filter's output
+     */
+    long byteNumber;
+
+    /**
+     * The Presentation Time Stamp(PTS) for the audio or video frame. It is based on 90KHz
+     * and has the same format as the PTS in ISO/IEC 13818-1.
+     */
+    long pts;
+
+    /**
+     * MPU sequence number of the filtered data. This is only used for MMTP.
+     */
+    int mpuSequenceNumber;
+
+    /**
+     * Specifies the address of the first macroblock in the slice defined in ITU-T Rec. H.264.
+     */
+    int firstMbInSlice;
+
+    /**
+     * TS index mask defined by DemuxTsIndex.
+     */
+    int tsIndexMask;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMonitorEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMonitorEvent.aidl
new file mode 100644
index 0000000..2dd11e2
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMonitorEvent.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.ScramblingStatus;
+
+/**
+ * Monitor event to notify monitored status change.
+ * @hide
+ */
+@VintfStability
+union DemuxFilterMonitorEvent {
+    /**
+     * New scrambling status.
+     */
+    ScramblingStatus scramblingStatus = ScramblingStatus.UNKNOWN;
+
+    /**
+     * New cid for the IP filter.
+     */
+    int cid;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMonitorEventType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMonitorEventType.aidl
new file mode 100644
index 0000000..87a4d9d
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMonitorEventType.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Monitor event type.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxFilterMonitorEventType {
+    SCRAMBLING_STATUS = 1 << 0,
+
+    IP_CID_CHANGE = 1 << 1,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterPesDataSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterPesDataSettings.aidl
new file mode 100644
index 0000000..56fbbfc
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterPesDataSettings.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Filter Settings for a PES Data.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterPesDataSettings {
+    int streamId;
+
+    /**
+     * true if the filter send onFilterStatus instead of onFilterEvent.
+     */
+    boolean isRaw;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterPesEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterPesEvent.aidl
new file mode 100644
index 0000000..0767c02
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterPesEvent.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Filter Event for PES data.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterPesEvent {
+    int streamId;
+
+    /**
+     * Data size in bytes of PES data
+     */
+    int dataLength;
+
+    /**
+     * MPU sequence number of filtered data (only for MMTP)
+     */
+    int mpuSequenceNumber;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterRecordSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterRecordSettings.aidl
new file mode 100644
index 0000000..475910b
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterRecordSettings.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterScIndexMask;
+import android.hardware.tv.tuner.DemuxRecordScIndexType;
+
+/**
+ * Filter Settings for Record data.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterRecordSettings {
+    /**
+     * Indexes defined by DemuxTsIndex.
+     */
+    int tsIndexMask;
+
+    DemuxRecordScIndexType scIndexType = DemuxRecordScIndexType.NONE;
+
+    DemuxFilterScIndexMask scIndexMask;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterScIndexMask.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterScIndexMask.aidl
new file mode 100644
index 0000000..4036b06
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterScIndexMask.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxScAvcIndex;
+import android.hardware.tv.tuner.DemuxScHevcIndex;
+import android.hardware.tv.tuner.DemuxScIndex;
+
+/**
+ * @hide
+ */
+@VintfStability
+union DemuxFilterScIndexMask {
+    /**
+     * Indexes defined by DemuxScIndex.
+     */
+    int scIndex;
+
+    /**
+     * Indexes defined by DemuxScAvcIndex.
+     */
+    int scAvc;
+
+    /**
+     * Indexes defined by DemuxScHevcIndex.
+     */
+    int scHevc;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionBits.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionBits.aidl
new file mode 100644
index 0000000..eea544f
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionBits.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Bits Settings for Section Filter.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterSectionBits {
+    /**
+     * The bytes are configured for Section Filter
+     */
+    byte[] filter;
+
+    /**
+     * Active bits in the configured bytes to be used for filtering
+     */
+    byte[] mask;
+
+    /**
+     * Do positive match at the bit position of the configured bytes when the
+     * bit at same position of the mode is 0.
+     * Do negative match at the bit position of the configured bytes when the
+     * bit at same position of the mode is 1.
+     */
+    byte[] mode;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl
new file mode 100644
index 0000000..a5f9ca7
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Filter Event for Section Filter.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterSectionEvent {
+    /**
+     * Table ID of filtered data
+     */
+    int tableId;
+
+    /**
+     * Version number of filtered data
+     */
+    int version;
+
+    /**
+     * Section number of filtered data
+     */
+    int sectionNum;
+
+    /**
+     * Data size in bytes of filtered data
+     */
+    long dataLength;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionSettings.aidl
new file mode 100644
index 0000000..f6788ee
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionSettings.aidl
@@ -0,0 +1,52 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterSectionSettingsCondition;
+
+/**
+ * Filter Settings for Section data according to ISO/IEC 13818-1.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterSectionSettings {
+    DemuxFilterSectionSettingsCondition condition;
+
+    /**
+     * true if the filter checks CRC and discards data with wrong CRC
+     */
+    boolean isCheckCrc;
+
+    /**
+     * true if the filter repeats the data.
+     *
+     * If false, for DemuxFilterSectionSettingsConditionTableInfo, HAL filters out all sections
+     * based on tableId and version, and stops filtering data. For DemuxFilterSectionBits, HAL
+     * filters out first section which matches the DemuxFilterSectionBits configuration, and stops
+     * filtering data.
+     *
+     * If true, for DemuxFilterSectionSettingsConditionTableInfo, HAL filters out all sections based
+     * on tableId and version, and repeats. For DemuxFilterSectionBits, HAL filters out sections
+     * which match the DemuxFilterSectionBits configuration, and repeats.
+     */
+    boolean isRepeat;
+
+    /**
+     * true if the filter send onFilterStatus instead of onFilterEvent.
+     */
+    boolean isRaw;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionSettingsCondition.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionSettingsCondition.aidl
new file mode 100644
index 0000000..374511a
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionSettingsCondition.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterSectionBits;
+import android.hardware.tv.tuner.DemuxFilterSectionSettingsConditionTableInfo;
+
+/**
+ * The union of Section Filter Bits Settings and Table information that can be
+ * set by client.
+ * @hide
+ */
+@VintfStability
+union DemuxFilterSectionSettingsCondition {
+    DemuxFilterSectionBits sectionBits;
+
+    DemuxFilterSectionSettingsConditionTableInfo tableInfo;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionSettingsConditionTableInfo.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionSettingsConditionTableInfo.aidl
new file mode 100644
index 0000000..dbd438c
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionSettingsConditionTableInfo.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Table information for Section Filter.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterSectionSettingsConditionTableInfo {
+    /**
+     * Table ID for Section Filter
+     */
+    int tableId;
+
+    /**
+     * Optional version number for Section Filter. It should be ignored if INVALID_TABINFO_VERSION
+     * is set.
+     */
+    int version;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSettings.aidl
new file mode 100644
index 0000000..7e9d2a1
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSettings.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxAlpFilterSettings;
+import android.hardware.tv.tuner.DemuxIpFilterSettings;
+import android.hardware.tv.tuner.DemuxMmtpFilterSettings;
+import android.hardware.tv.tuner.DemuxTlvFilterSettings;
+import android.hardware.tv.tuner.DemuxTsFilterSettings;
+
+/**
+ * Filter Settings.
+ * @hide
+ */
+@VintfStability
+union DemuxFilterSettings {
+    DemuxTsFilterSettings ts;
+
+    DemuxMmtpFilterSettings mmtp;
+
+    DemuxIpFilterSettings ip;
+
+    DemuxTlvFilterSettings tlv;
+
+    DemuxAlpFilterSettings alp;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterStatus.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterStatus.aidl
new file mode 100644
index 0000000..e6f3b63
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterStatus.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * A status of data in the filter's buffer.
+ * @hide
+ */
+@VintfStability
+@Backing(type="byte")
+enum DemuxFilterStatus {
+    /**
+     * The data in the filter buffer is ready to be read. It can also be used to know the STC
+     * (System Time Clock) ready status if it's PCR filter.
+     */
+    DATA_READY = 1 << 0,
+
+    /**
+     * The available data amount in the filter buffer is at low level which is
+     * set to 25 percent by default.
+     */
+    LOW_WATER = 1 << 1,
+
+    /**
+     * The available data amount in the filter buffer is at high level which is
+     * set to 75 percent by default.
+     */
+    HIGH_WATER = 1 << 2,
+
+    /**
+     * The data in the filter buffer is full and newly filtered data is being
+     * discarded.
+     */
+    OVERFLOW = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSubType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSubType.aidl
new file mode 100644
index 0000000..3dfc0ae
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSubType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxAlpFilterType;
+import android.hardware.tv.tuner.DemuxIpFilterType;
+import android.hardware.tv.tuner.DemuxMmtpFilterType;
+import android.hardware.tv.tuner.DemuxTlvFilterType;
+import android.hardware.tv.tuner.DemuxTsFilterType;
+
+/**
+ * The different Demux Filter Sub Types.
+ * @hide
+ */
+@VintfStability
+union DemuxFilterSubType {
+    DemuxTsFilterType tsFilterType = DemuxTsFilterType.UNDEFINED;
+
+    DemuxMmtpFilterType mmtpFilterType;
+
+    DemuxIpFilterType ipFilterType;
+
+    DemuxTlvFilterType tlvFilterType;
+
+    DemuxAlpFilterType alpFilterType;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterTemiEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterTemiEvent.aidl
new file mode 100644
index 0000000..a752e7c
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterTemiEvent.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Filter Event for Timed External Media Information (TEMI) data.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterTemiEvent {
+    /**
+     * Presentation Time Stamp for audio or video frame. It based on 90KHz has
+     * the same format as PTS (Presentation Time Stamp) in ISO/IEC 13818-1.
+     */
+    long pts;
+
+    /**
+     * TEMI Descriptor Tag
+     */
+    byte descrTag;
+
+    /**
+     * TEMI Descriptor
+     */
+    byte[] descrData;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterTsRecordEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterTsRecordEvent.aidl
new file mode 100644
index 0000000..4992a33
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterTsRecordEvent.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterScIndexMask;
+import android.hardware.tv.tuner.DemuxPid;
+
+/**
+ * Filter Event for TS Record data.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterTsRecordEvent {
+    DemuxPid pid;
+
+    /**
+     * Indexes defined by DemuxTsIndex.
+     */
+    int tsIndexMask;
+
+    /**
+     * Indexes of record output
+     */
+    DemuxFilterScIndexMask scIndexMask;
+
+    /**
+     * Byte number from beginning of the filter's output
+     */
+    long byteNumber;
+
+    /**
+     * The Presentation Time Stamp(PTS) for the audio or video frame. It is based on 90KHz
+     * and has the same format as the PTS in ISO/IEC 13818-1.
+     */
+    long pts;
+
+    /**
+     * Specifies the address of the first macroblock in the slice defined in ITU-T Rec. H.264.
+     */
+    int firstMbInSlice;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterType.aidl
new file mode 100644
index 0000000..f5eda60
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterType.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterMainType;
+import android.hardware.tv.tuner.DemuxFilterSubType;
+
+/**
+ * Demux Filter Type.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxFilterType {
+    DemuxFilterMainType mainType = DemuxFilterMainType.UNDEFINED;
+
+    DemuxFilterSubType subType;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpAddress.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpAddress.aidl
new file mode 100644
index 0000000..c088cdc
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpAddress.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxIpAddressIpAddress;
+
+/**
+ * IP Settings for a IP filter.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxIpAddress {
+    DemuxIpAddressIpAddress srcIpAddress;
+
+    DemuxIpAddressIpAddress dstIpAddress;
+
+    /**
+     * 0 is invalid. should be ignored.
+     */
+    int srcPort;
+
+    /**
+     * 0 is invalid. should be ignored.
+     */
+    int dstPort;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpAddressIpAddress.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpAddressIpAddress.aidl
new file mode 100644
index 0000000..1a57215
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpAddressIpAddress.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * @hide
+ */
+@VintfStability
+union DemuxIpAddressIpAddress {
+    /**
+     * 0.0.0.0 is invalid. should be ignored.
+     */
+    byte[] v4 = {};
+
+    /**
+     * 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 is invalid. should be ignored.
+     */
+    byte[] v6;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpFilterSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpFilterSettings.aidl
new file mode 100644
index 0000000..6265aa6
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpFilterSettings.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxIpAddress;
+import android.hardware.tv.tuner.DemuxIpFilterSettingsFilterSettings;
+
+/**
+ * Filter Settings for a IP filter.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxIpFilterSettings {
+    DemuxIpAddress ipAddr;
+
+    DemuxIpFilterSettingsFilterSettings filterSettings;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpFilterSettingsFilterSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpFilterSettingsFilterSettings.aidl
new file mode 100644
index 0000000..b8aa9f2
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpFilterSettingsFilterSettings.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterSectionSettings;
+
+/**
+ * @hide
+ */
+@VintfStability
+union DemuxIpFilterSettingsFilterSettings {
+    /**
+     * Not additional parameters. it's used by NTP, IP_PAYLOAD,
+     * PAYLOAD_THROUGH subtype filters.
+     */
+    boolean noinit;
+
+    DemuxFilterSectionSettings section;
+
+    /**
+     * true if the data from IP subtype go to next filter directly
+     */
+    boolean bPassthrough;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpFilterType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpFilterType.aidl
new file mode 100644
index 0000000..f975195
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxIpFilterType.aidl
@@ -0,0 +1,56 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * IP Filter Type.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxIpFilterType {
+    UNDEFINED,
+
+    /**
+     * A filter to filter section data out from input stream, and queue the
+     * data to the filter's FMQ (Fast Message Queue).
+     */
+    SECTION,
+
+    /**
+     * A filter to set NTP (Network Time Procotol) channel from input stream.
+     */
+    NTP,
+
+    /**
+     * A filter to strip out IP message header and queue the data to the
+     * filter's FMQ.
+     */
+    IP_PAYLOAD,
+
+    /**
+     * A filter to filter a IP stream out from input stream. The output can be
+     * either upper stream of another filter or queued to the filter's FMQ.
+     */
+    IP,
+
+    /**
+     * A filter to strip out IP message header and be a data source of another
+     * filter.
+     */
+    PAYLOAD_THROUGH,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxMmtpFilterSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxMmtpFilterSettings.aidl
new file mode 100644
index 0000000..8093d63
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxMmtpFilterSettings.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxMmtpFilterSettingsFilterSettings;
+
+/**
+ * Filter Settings for a MMTP filter.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxMmtpFilterSettings {
+    int mmtpPid;
+
+    DemuxMmtpFilterSettingsFilterSettings filterSettings;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxMmtpFilterSettingsFilterSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxMmtpFilterSettingsFilterSettings.aidl
new file mode 100644
index 0000000..0f960b6
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxMmtpFilterSettingsFilterSettings.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterAvSettings;
+import android.hardware.tv.tuner.DemuxFilterDownloadSettings;
+import android.hardware.tv.tuner.DemuxFilterPesDataSettings;
+import android.hardware.tv.tuner.DemuxFilterRecordSettings;
+import android.hardware.tv.tuner.DemuxFilterSectionSettings;
+
+/**
+ * The different types of MMTP Filter Settings that can be set by client.
+ * @hide
+ */
+@VintfStability
+union DemuxMmtpFilterSettingsFilterSettings {
+    /**
+     * Not additional parameters. it's used by MMTP subtype filters.
+     */
+    boolean noinit;
+
+    DemuxFilterSectionSettings section;
+
+    DemuxFilterAvSettings av;
+
+    DemuxFilterPesDataSettings pesData;
+
+    DemuxFilterRecordSettings record;
+
+    DemuxFilterDownloadSettings download;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxMmtpFilterType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxMmtpFilterType.aidl
new file mode 100644
index 0000000..eb0016c
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxMmtpFilterType.aidl
@@ -0,0 +1,69 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * MMTP Filter Type according to ISO/IEC 23008-1
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxMmtpFilterType {
+    UNDEFINED,
+
+    /**
+     * A filter to filter signaling data out from input stream, and queue the
+     * data to the filter's FMQ (Fast Message Queue).
+     */
+    SECTION,
+
+    /**
+     * A filter to filter MFU (Media fragment unit) out from input stream, and
+     * queue the data to the filter's FMQ.
+     */
+    PES,
+
+    /**
+     * A filter to filter a MMTP stream out from input stream, and queue the
+     * data to the filter's FMQ.
+     */
+    MMTP,
+
+    /**
+     * A filter to filter Audio data out from input stream, and send Audio's
+     * Metadata to client through onFilterEvent.
+     */
+    AUDIO,
+
+    /**
+     * A filter to filter Video data out from input stream, and send Video's
+     * Metadata to client through onFilterEvent.
+     */
+    VIDEO,
+
+    /**
+     * A filter to filter data out from input stream, and queue the data to the
+     * buffer of the record.
+     */
+    RECORD,
+
+    /**
+     * A filter to filter application data out from input stream, and queue the
+     * data to the filter's FMQ.
+     */
+    DOWNLOAD,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxPid.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxPid.aidl
new file mode 100644
index 0000000..7513454
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxPid.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Demux Packet ID.
+ * @hide
+ */
+@VintfStability
+union DemuxPid {
+    /**
+     * Packet ID is used to specify packets in transport stream.
+     */
+    int tPid;
+
+    /**
+     * Packet ID is used to specify packets in MMTP.
+     */
+    int mmtpPid;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.aidl
new file mode 100644
index 0000000..b8858ef
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * The bits of EventFlag in FMQ (Fast message queue) are used by client to
+ * notify HAL the status change.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxQueueNotifyBits {
+    /**
+     * client writes data and notify HAL the data is ready.
+     */
+    DATA_READY = 1 << 0,
+
+    /**
+     * client reads data and notify HAL the data is consumed.
+     */
+    DATA_CONSUMED = 1 << 1,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxRecordScIndexType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxRecordScIndexType.aidl
new file mode 100644
index 0000000..98427f7
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxRecordScIndexType.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Start Code Index type to be used in the filter for record
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxRecordScIndexType {
+    /**
+     * Don't use SC index
+     */
+    NONE,
+
+    /**
+     * Use Start Code index
+     */
+    SC,
+
+    /**
+     * Use Start Code index for HEVC
+     */
+    SC_HEVC,
+
+    /**
+     * Use Start Code index for AVC
+     */
+    SC_AVC,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxScAvcIndex.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxScAvcIndex.aidl
new file mode 100644
index 0000000..ed418f2
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxScAvcIndex.aidl
@@ -0,0 +1,52 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Indexes can be tagged by start point of slice groups according to ISO/IEC 14496-10.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxScAvcIndex {
+    UNDEFINED = 0,
+
+    /**
+     * All blocks are coded as I blocks.
+     */
+    I_SLICE = 1 << 0,
+
+    /**
+     * Blocks are coded as I or P blocks.
+     */
+    P_SLICE = 1 << 1,
+
+    /**
+     * Blocks are coded as I, P or B blocks.
+     */
+    B_SLICE = 1 << 2,
+
+    /**
+     * A so-called switching I slice that is coded.
+     */
+    SI_SLICE = 1 << 3,
+
+    /**
+     * A so-called switching P slice that is coded.
+     */
+    SP_SLICE = 1 << 4,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxScHevcIndex.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxScHevcIndex.aidl
new file mode 100644
index 0000000..0d1f112
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxScHevcIndex.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Indexes can be tagged by NAL unit group in HEVC according to ISO/IEC 23008-2.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxScHevcIndex {
+    UNDEFINED = 0,
+
+    SPS = 1 << 0,
+
+    AUD = 1 << 1,
+
+    SLICE_CE_BLA_W_LP = 1 << 2,
+
+    SLICE_BLA_W_RADL = 1 << 3,
+
+    SLICE_BLA_N_LP = 1 << 4,
+
+    SLICE_IDR_W_RADL = 1 << 5,
+
+    SLICE_IDR_N_LP = 1 << 6,
+
+    SLICE_TRAIL_CRA = 1 << 7,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxScIndex.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxScIndex.aidl
new file mode 100644
index 0000000..4fed1e5
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxScIndex.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Indexes can be tagged by Start Code in PES (Packetized Elementary Stream)
+ * according to ISO/IEC 13818-1.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxScIndex {
+    UNDEFINED = 0,
+
+    /**
+     * Start Code is for a new I Frame
+     */
+    I_FRAME = 1 << 0,
+
+    /**
+     * Start Code is for a new P Frame
+     */
+    P_FRAME = 1 << 1,
+
+    /**
+     * Start Code is for a new B Frame
+     */
+    B_FRAME = 1 << 2,
+
+    /**
+     * Start Code is for a new Sequence
+     */
+    SEQUENCE = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTlvFilterSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTlvFilterSettings.aidl
new file mode 100644
index 0000000..7a215e7
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTlvFilterSettings.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxTlvFilterSettingsFilterSettings;
+
+/**
+ * Filter Settings for a TLV filter.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxTlvFilterSettings {
+    /**
+     * Packet type according to ITU-R BT.1869.
+     * 0x01: IPv4 packet
+     * 0x02: IPv6 packet
+     * 0x03: IP packet with header compression
+     * 0xFE: Signaling packet
+     * 0xFF: NULL packet
+     */
+    int packetType;
+
+    /**
+     * true if the filtered data is commpressed ip packet
+     */
+    boolean isCompressedIpPacket;
+
+    DemuxTlvFilterSettingsFilterSettings filterSettings;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTlvFilterSettingsFilterSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTlvFilterSettingsFilterSettings.aidl
new file mode 100644
index 0000000..7837c1d
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTlvFilterSettingsFilterSettings.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterSectionSettings;
+
+/**
+ * The different types of TLV Filter Settings that can be set by client.
+ * @hide
+ */
+@VintfStability
+union DemuxTlvFilterSettingsFilterSettings {
+    /**
+     * Not additional parameters. it's used by PAYLOAD_THROUGH subtype
+     * filters.
+     */
+    boolean noinit;
+
+    DemuxFilterSectionSettings section;
+
+    /**
+     * true if the data from TLV subtype go to next filter directly
+     */
+    boolean bPassthrough;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTlvFilterType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTlvFilterType.aidl
new file mode 100644
index 0000000..1566f74
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTlvFilterType.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * TLV Filter Type according to ITU-R BT.1869.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxTlvFilterType {
+    UNDEFINED,
+
+    /**
+     * A filter to filter signaling data out from input stream, and queue the
+     * data to the filter's FMQ (Fast Message Queue).
+     */
+    SECTION,
+
+    /**
+     * A filter to filter a TLV stream out from input stream. The output can be
+     * either upper stream of another filter or queued to the filter's FMQ.
+     */
+    TLV,
+
+    /**
+     * A filter to strip out TLV message header and be a data source of another
+     * filter.
+     */
+    PAYLOAD_THROUGH,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsFilterSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsFilterSettings.aidl
new file mode 100644
index 0000000..0fc40d6
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsFilterSettings.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxTsFilterSettingsFilterSettings;
+
+/**
+ * Filter Settings for a TS filter.
+ * @hide
+ */
+@VintfStability
+parcelable DemuxTsFilterSettings {
+    /**
+     * Packet ID is used to specify packets in transport stream.
+     */
+    int tpid;
+
+    DemuxTsFilterSettingsFilterSettings filterSettings;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsFilterSettingsFilterSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsFilterSettingsFilterSettings.aidl
new file mode 100644
index 0000000..81e36f3
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsFilterSettingsFilterSettings.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterAvSettings;
+import android.hardware.tv.tuner.DemuxFilterPesDataSettings;
+import android.hardware.tv.tuner.DemuxFilterRecordSettings;
+import android.hardware.tv.tuner.DemuxFilterSectionSettings;
+
+/**
+ * The different types of TS Filter Settings that can be set by client.
+ * @hide
+ */
+@VintfStability
+union DemuxTsFilterSettingsFilterSettings {
+    /**
+     * Not additional parameters. it's used by PCR, TS, TEMI subtype
+     * filters.
+     */
+    boolean noinit;
+
+    DemuxFilterSectionSettings section;
+
+    DemuxFilterAvSettings av;
+
+    DemuxFilterPesDataSettings pesData;
+
+    DemuxFilterRecordSettings record;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsFilterType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsFilterType.aidl
new file mode 100644
index 0000000..cdf5c58
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsFilterType.aidl
@@ -0,0 +1,75 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * TS Filter Type according to ISO/IEC 13818-1
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxTsFilterType {
+    UNDEFINED,
+
+    /**
+     * A filter to filter Section data out from input stream, and queue the
+     * data to the filter's FMQ (Fast Message Queue).
+     */
+    SECTION,
+
+    /**
+     * A filter to filter Packetized Elementary Stream data out from input
+     * stream, and queue the data to the filter's FMQ.
+     */
+    PES,
+
+    /**
+     * A filter to filter a Transport Stream out from input stream, and queue
+     * the data to the filter's FMQ.
+     */
+    TS,
+
+    /**
+     * A filter to filter Audio data out from input stream, and send Audio's
+     * Metadata to client through onFilterEvent.
+     */
+    AUDIO,
+
+    /**
+     * A filter to filter Video data out from input stream, and send Video's
+     * Metadata to client through onFilterEvent.
+     */
+    VIDEO,
+
+    /**
+     * A filter to set PCR (Program Clock Reference) channel from input stream.
+     */
+    PCR,
+
+    /**
+     * A filter to filter data out from input stream, and queue the data to the
+     * buffer of the record.
+     */
+    RECORD,
+
+    /**
+     * A filter to filter out Timed External Media Information (TEMI) according
+     * to ISO/IEC 13818-1:2013/ DAM 6 from input stream, and send TEMI event to
+     * client through onFilterEvent.
+     */
+    TEMI,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsIndex.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsIndex.aidl
new file mode 100644
index 0000000..9d0e7c5
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxTsIndex.aidl
@@ -0,0 +1,76 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Indexes can be tagged through TS (Transport Stream) header.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DemuxTsIndex {
+    FIRST_PACKET = 1 << 0,
+
+    PAYLOAD_UNIT_START_INDICATOR = 1 << 1,
+
+    CHANGE_TO_NOT_SCRAMBLED = 1 << 2,
+
+    CHANGE_TO_EVEN_SCRAMBLED = 1 << 3,
+
+    CHANGE_TO_ODD_SCRAMBLED = 1 << 4,
+
+    DISCONTINUITY_INDICATOR = 1 << 5,
+
+    RANDOM_ACCESS_INDICATOR = 1 << 6,
+
+    PRIORITY_INDICATOR = 1 << 7,
+
+    PCR_FLAG = 1 << 8,
+
+    OPCR_FLAG = 1 << 9,
+
+    SPLICING_POINT_FLAG = 1 << 10,
+
+    PRIVATE_DATA = 1 << 11,
+
+    ADAPTATION_EXTENSION_FLAG = 1 << 12,
+
+    /**
+     * Index the address of MMT Packet Table(MPT).
+     */
+    MPT_INDEX_MPT = 1 << 16,
+
+    /**
+     * Index the address of Video.
+     */
+    MPT_INDEX_VIDEO = 1 << 17,
+
+    /**
+     * Index the address of Audio.
+     */
+    MPT_INDEX_AUDIO = 1 << 18,
+
+    /**
+     * Index to indicate this is a target of timestamp extraction for video.
+     */
+    MPT_INDEX_TIMESTAMP_TARGET_VIDEO = 1 << 19,
+
+    /**
+     * Index to indicate this is a target of timestamp extraction for audio.
+     */
+    MPT_INDEX_TIMESTAMP_TARGET_AUDIO = 1 << 20,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DvrSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DvrSettings.aidl
new file mode 100644
index 0000000..aa21cf6
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DvrSettings.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.PlaybackSettings;
+import android.hardware.tv.tuner.RecordSettings;
+
+/**
+ * The Setting for DVR.
+ * @hide
+ */
+@VintfStability
+union DvrSettings {
+    RecordSettings record;
+
+    PlaybackSettings playback;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DvrType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DvrType.aidl
new file mode 100644
index 0000000..21dcc4a
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DvrType.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * The type of DVR.
+ * @hide
+ */
+@VintfStability
+@Backing(type="byte")
+enum DvrType {
+    RECORD,
+
+    PLAYBACK,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FilterDelayHint.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FilterDelayHint.aidl
new file mode 100644
index 0000000..3f1ca35
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FilterDelayHint.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FilterDelayHintType;
+
+/**
+ * Filter Delay Hint
+ * Gives information to the filter to assist in delaying / accumulating filter events.
+ * See FilterDelayHintType for more information regarding the hintValue units.
+ * Note: this hint is not valid for media filters.
+ * @hide
+ */
+@VintfStability
+parcelable FilterDelayHint {
+    FilterDelayHintType hintType = FilterDelayHintType.INVALID;
+    int hintValue;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FilterDelayHintType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FilterDelayHintType.aidl
new file mode 100644
index 0000000..f5b1454
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FilterDelayHintType.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Filter Delay Hint Type
+ * Specifies the type of filter delay.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FilterDelayHintType {
+    /**
+     * Invalid type to be used as default value.
+     */
+    INVALID,
+
+    /**
+     * Hint that can be used by the filter implementation to make decisions about
+     * delaying the filter callback until a specified amount of time has passed.
+     * For time delays, the hint value contains time in milliseconds.
+     */
+    TIME_DELAY_IN_MS,
+
+    /**
+     * Hint that can be used by the filter implementation to make decisions about
+     * delaying the filter callback until a specified amount of data has been
+     * accumulated.
+     * For data size delays, the hint value contains the data size in bytes.
+     */
+    DATA_SIZE_DELAY_IN_BYTES,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogAftFlag.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogAftFlag.aidl
new file mode 100644
index 0000000..72291a5
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogAftFlag.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * AFT flag for an Analog Frontend.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendAnalogAftFlag {
+    UNDEFINED,
+
+    AFT_TRUE,
+
+    AFT_FALSE,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogCapabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogCapabilities.aidl
new file mode 100644
index 0000000..7f0cd04
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogCapabilities.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Capabilities for Analog Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendAnalogCapabilities {
+    /**
+     * Signal Types defined by FrontendAnalogType.
+     */
+    int typeCap;
+
+    /**
+     * Standard Interchange Formats defined by FrontendAnalogSifStandard.
+     */
+    int sifStandardCap;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogSettings.aidl
new file mode 100644
index 0000000..0a3646d
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogSettings.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAnalogAftFlag;
+import android.hardware.tv.tuner.FrontendAnalogSifStandard;
+import android.hardware.tv.tuner.FrontendAnalogType;
+import android.hardware.tv.tuner.FrontendSpectralInversion;
+
+/**
+ * Signal Settings for Analog Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendAnalogSettings {
+    /**
+     * Signal frequency in Hertz
+     */
+    long frequency;
+
+    /**
+     * Signal end frequency in Hertz used by scan
+     */
+    long endFrequency;
+
+    FrontendSpectralInversion inversion = FrontendSpectralInversion.UNDEFINED;
+
+    FrontendAnalogType type = FrontendAnalogType.UNDEFINED;
+
+    FrontendAnalogAftFlag aftFlag = FrontendAnalogAftFlag.UNDEFINED;
+
+    FrontendAnalogSifStandard sifStandard = FrontendAnalogSifStandard.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogSifStandard.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogSifStandard.aidl
new file mode 100644
index 0000000..3c0f9b4
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogSifStandard.aidl
@@ -0,0 +1,63 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Standard Interchange Format (SIF) for Analog Frontend.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendAnalogSifStandard {
+    UNDEFINED = 0,
+
+    AUTO = 1 << 0,
+
+    BG = 1 << 1,
+
+    BG_A2 = 1 << 2,
+
+    BG_NICAM = 1 << 3,
+
+    I = 1 << 4,
+
+    DK = 1 << 5,
+
+    DK1_A2 = 1 << 6,
+
+    DK2_A2 = 1 << 7,
+
+    DK3_A2 = 1 << 8,
+
+    DK_NICAM = 1 << 9,
+
+    L = 1 << 10,
+
+    M = 1 << 11,
+
+    M_BTSC = 1 << 12,
+
+    M_A2 = 1 << 13,
+
+    M_EIAJ = 1 << 14,
+
+    I_NICAM = 1 << 15,
+
+    L_NICAM = 1 << 16,
+
+    L_PRIME = 1 << 17,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogType.aidl
new file mode 100644
index 0000000..e4b05a6
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAnalogType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Signal Type for Analog Frontend.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendAnalogType {
+    UNDEFINED = 0,
+
+    AUTO = 1 << 0,
+
+    PAL = 1 << 1,
+
+    PAL_M = 1 << 2,
+
+    PAL_N = 1 << 3,
+
+    PAL_60 = 1 << 4,
+
+    NTSC = 1 << 5,
+
+    NTSC_443 = 1 << 6,
+
+    SECAM = 1 << 7,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Bandwidth.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Bandwidth.aidl
new file mode 100644
index 0000000..af78a96
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Bandwidth.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Bandwidth for ATSC3.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendAtsc3Bandwidth {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set bandwidth automatically
+     */
+    AUTO = 1 << 0,
+
+    BANDWIDTH_6MHZ = 1 << 1,
+
+    BANDWIDTH_7MHZ = 1 << 2,
+
+    BANDWIDTH_8MHZ = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Capabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Capabilities.aidl
new file mode 100644
index 0000000..98c7b8d
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Capabilities.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Capabilities for ATSC3 Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendAtsc3Capabilities {
+    /**
+     * Bandwidth capabilities defined by FrontendAtsc3Bandwidth.
+     */
+    int bandwidthCap;
+
+    /**
+     * Modulation capabilities defined by FrontendAtsc3Modulation.
+     */
+    int modulationCap;
+
+    /**
+     * TimeInterleaveMode capabilities defined by FrontendAtsc3TimeInterleaveMode.
+     */
+    int timeInterleaveModeCap;
+
+    /**
+     * CodeRate capabilities defined by FrontendAtsc3CodeRate.
+     */
+    int codeRateCap;
+
+    /**
+     * FEC capabilities defined by FrontendAtsc3Fec.
+     */
+    int fecCap;
+
+    /**
+     * Demodulator Output Format capabilities FrontendAtsc3DemodOutputFormat.
+     */
+    byte demodOutputFormatCap;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3CodeRate.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3CodeRate.aidl
new file mode 100644
index 0000000..8a2ee03
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3CodeRate.aidl
@@ -0,0 +1,56 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Code Rate for ATSC3.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendAtsc3CodeRate {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Coderate automatically
+     */
+    AUTO = 1 << 0,
+
+    CODERATE_2_15 = 1 << 1,
+
+    CODERATE_3_15 = 1 << 2,
+
+    CODERATE_4_15 = 1 << 3,
+
+    CODERATE_5_15 = 1 << 4,
+
+    CODERATE_6_15 = 1 << 5,
+
+    CODERATE_7_15 = 1 << 6,
+
+    CODERATE_8_15 = 1 << 7,
+
+    CODERATE_9_15 = 1 << 8,
+
+    CODERATE_10_15 = 1 << 9,
+
+    CODERATE_11_15 = 1 << 10,
+
+    CODERATE_12_15 = 1 << 11,
+
+    CODERATE_13_15 = 1 << 12,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3DemodOutputFormat.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3DemodOutputFormat.aidl
new file mode 100644
index 0000000..b17616c
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3DemodOutputFormat.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Demodulator Output Format for an ATSC3 Frontend.
+ * @hide
+ */
+@VintfStability
+@Backing(type="byte")
+enum FrontendAtsc3DemodOutputFormat {
+    /**
+     * Undefined. Scan uses this.
+     */
+    UNDEFINED = 0,
+
+    /**
+     * ALP format. Typically used in US region.
+     */
+    ATSC3_LINKLAYER_PACKET = 1 << 0,
+
+    /**
+     * BaseBand packet format. Typically used in Korea region.
+     */
+    BASEBAND_PACKET = 1 << 1,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Fec.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Fec.aidl
new file mode 100644
index 0000000..af0bf04
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Fec.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Forward Error Correction (FEC) for ATSC3.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendAtsc3Fec {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set FEC automatically
+     */
+    AUTO = 1 << 0,
+
+    BCH_LDPC_16K = 1 << 1,
+
+    BCH_LDPC_64K = 1 << 2,
+
+    CRC_LDPC_16K = 1 << 3,
+
+    CRC_LDPC_64K = 1 << 4,
+
+    LDPC_16K = 1 << 5,
+
+    LDPC_64K = 1 << 6,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Modulation.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Modulation.aidl
new file mode 100644
index 0000000..3108234
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Modulation.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Modulation Type for ATSC3.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendAtsc3Modulation {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set modulation automatically
+     */
+    AUTO = 1 << 0,
+
+    MOD_QPSK = 1 << 1,
+
+    MOD_16QAM = 1 << 2,
+
+    MOD_64QAM = 1 << 3,
+
+    MOD_256QAM = 1 << 4,
+
+    MOD_1024QAM = 1 << 5,
+
+    MOD_4096QAM = 1 << 6,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3PlpSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3PlpSettings.aidl
new file mode 100644
index 0000000..b7e2295
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3PlpSettings.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAtsc3CodeRate;
+import android.hardware.tv.tuner.FrontendAtsc3Fec;
+import android.hardware.tv.tuner.FrontendAtsc3Modulation;
+import android.hardware.tv.tuner.FrontendAtsc3TimeInterleaveMode;
+
+/**
+ * PLP basis Signal Settings for an ATSC3 Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendAtsc3PlpSettings {
+    int plpId;
+
+    FrontendAtsc3Modulation modulation = FrontendAtsc3Modulation.UNDEFINED;
+
+    FrontendAtsc3TimeInterleaveMode interleaveMode = FrontendAtsc3TimeInterleaveMode.UNDEFINED;
+
+    FrontendAtsc3CodeRate codeRate = FrontendAtsc3CodeRate.UNDEFINED;
+
+    FrontendAtsc3Fec fec = FrontendAtsc3Fec.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Settings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Settings.aidl
new file mode 100644
index 0000000..981adc5
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3Settings.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAtsc3Bandwidth;
+import android.hardware.tv.tuner.FrontendAtsc3DemodOutputFormat;
+import android.hardware.tv.tuner.FrontendAtsc3PlpSettings;
+import android.hardware.tv.tuner.FrontendSpectralInversion;
+
+/**
+ * Signal Settings for an ATSC3 Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendAtsc3Settings {
+    /**
+     * Signal frequency in Hertz
+     */
+    long frequency;
+
+    /**
+     * Signal end frequency in Hertz used by scan
+     */
+    long endFrequency;
+
+    /**
+     * Bandwidth of tuning band.
+     */
+    FrontendAtsc3Bandwidth bandwidth = FrontendAtsc3Bandwidth.UNDEFINED;
+
+    FrontendSpectralInversion inversion = FrontendSpectralInversion.UNDEFINED;
+
+    FrontendAtsc3DemodOutputFormat demodOutputFormat = FrontendAtsc3DemodOutputFormat.UNDEFINED;
+
+    FrontendAtsc3PlpSettings[] plpSettings;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3TimeInterleaveMode.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3TimeInterleaveMode.aidl
new file mode 100644
index 0000000..451a922
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtsc3TimeInterleaveMode.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Time Interleave Mode for ATSC3.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendAtsc3TimeInterleaveMode {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set TimeInterleaveMode automatically
+     */
+    AUTO = 1 << 0,
+
+    CTI = 1 << 1,
+
+    HTI = 1 << 2,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtscCapabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtscCapabilities.aidl
new file mode 100644
index 0000000..c8a3d2b
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtscCapabilities.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAtscModulation;
+
+/**
+ * Capabilities for ATSC Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendAtscCapabilities {
+    /**
+     * Modulation capabilities defined by FrontendAtscModulation.
+     */
+    int modulationCap;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtscModulation.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtscModulation.aidl
new file mode 100644
index 0000000..960a299
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtscModulation.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Modulation Type for ATSC.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendAtscModulation {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set modulation automatically
+     */
+    AUTO = 1 << 0,
+
+    MOD_8VSB = 1 << 2,
+
+    MOD_16VSB = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtscSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtscSettings.aidl
new file mode 100644
index 0000000..f9d267e
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendAtscSettings.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAtscModulation;
+import android.hardware.tv.tuner.FrontendSpectralInversion;
+
+/**
+ * Signal Settings for an ATSC Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendAtscSettings {
+    /**
+     * Signal frequency in Hertz
+     */
+    long frequency;
+
+    /**
+     * Signal end frequency in Hertz used by scan
+     */
+    long endFrequency;
+
+    FrontendSpectralInversion inversion = FrontendSpectralInversion.UNDEFINED;
+
+    FrontendAtscModulation modulation = FrontendAtscModulation.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendBandwidth.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendBandwidth.aidl
new file mode 100644
index 0000000..c1c2355
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendBandwidth.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAtsc3Bandwidth;
+import android.hardware.tv.tuner.FrontendDvbtBandwidth;
+import android.hardware.tv.tuner.FrontendIsdbtBandwidth;
+import android.hardware.tv.tuner.FrontendDtmbBandwidth;
+import android.hardware.tv.tuner.FrontendDvbcBandwidth;
+
+/**
+ * @hide
+ */
+@VintfStability
+union FrontendBandwidth {
+    FrontendAtsc3Bandwidth atsc3 = FrontendAtsc3Bandwidth.UNDEFINED;
+
+    FrontendDvbcBandwidth dvbc;
+
+    FrontendDvbtBandwidth dvbt;
+
+    FrontendIsdbtBandwidth isdbt;
+
+    FrontendDtmbBandwidth dtmb;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendCableTimeInterleaveMode.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendCableTimeInterleaveMode.aidl
new file mode 100644
index 0000000..a2b4356
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendCableTimeInterleaveMode.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Time Interleave Mode for DVBC Frontend.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendCableTimeInterleaveMode {
+    UNDEFINED = 0,
+
+    AUTO = 1 << 0,
+
+    INTERLEAVING_128_1_0 = 1 << 1,
+
+    INTERLEAVING_128_1_1 = 1 << 2,
+
+    INTERLEAVING_64_2 = 1 << 3,
+
+    INTERLEAVING_32_4 = 1 << 4,
+
+    INTERLEAVING_16_8 = 1 << 5,
+
+    INTERLEAVING_8_16 = 1 << 6,
+
+    INTERLEAVING_128_2 = 1 << 7,
+
+    INTERLEAVING_128_3 = 1 << 8,
+
+    INTERLEAVING_128_4 = 1 << 9,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendCapabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendCapabilities.aidl
new file mode 100644
index 0000000..a6f1490
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendCapabilities.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAnalogCapabilities;
+import android.hardware.tv.tuner.FrontendAtsc3Capabilities;
+import android.hardware.tv.tuner.FrontendAtscCapabilities;
+import android.hardware.tv.tuner.FrontendDtmbCapabilities;
+import android.hardware.tv.tuner.FrontendDvbcCapabilities;
+import android.hardware.tv.tuner.FrontendDvbsCapabilities;
+import android.hardware.tv.tuner.FrontendDvbtCapabilities;
+import android.hardware.tv.tuner.FrontendIsdbs3Capabilities;
+import android.hardware.tv.tuner.FrontendIsdbsCapabilities;
+import android.hardware.tv.tuner.FrontendIsdbtCapabilities;
+
+/**
+ * @hide
+ */
+@VintfStability
+union FrontendCapabilities {
+    FrontendAnalogCapabilities analogCaps;
+
+    FrontendAtscCapabilities atscCaps;
+
+    FrontendAtsc3Capabilities atsc3Caps;
+
+    FrontendDtmbCapabilities dtmbCaps;
+
+    FrontendDvbsCapabilities dvbsCaps;
+
+    FrontendDvbcCapabilities dvbcCaps;
+
+    FrontendDvbtCapabilities dvbtCaps;
+
+    FrontendIsdbsCapabilities isdbsCaps;
+
+    FrontendIsdbs3Capabilities isdbs3Caps;
+
+    FrontendIsdbtCapabilities isdbtCaps;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbBandwidth.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbBandwidth.aidl
new file mode 100644
index 0000000..4dc3f0f
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbBandwidth.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Bandwidth Type for DTMB.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDtmbBandwidth {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Bandwidth automatically
+     */
+    AUTO = 1 << 0,
+
+    BANDWIDTH_8MHZ = 1 << 1,
+
+    BANDWIDTH_6MHZ = 1 << 2,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbCapabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbCapabilities.aidl
new file mode 100644
index 0000000..eda0d46
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbCapabilities.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Capabilities for DTMB Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendDtmbCapabilities {
+    /**
+     * Transmission Modes defined by FrontendDtmbTransmissionMode.
+     */
+    int transmissionModeCap;
+
+    /**
+     * Bandwidth Types defined by FrontendDtmbBandwidth.
+     */
+    int bandwidthCap;
+
+    /**
+     * Modulations defined by FrontendDtmbModulation.
+     */
+    int modulationCap;
+
+    /**
+     * CODERATE Types defined by FrontendDtmbCodeRate.
+     */
+    int codeRateCap;
+
+    /**
+     * Guard Interval Types defined by FrontendDtmbGuardInterval.
+     */
+    int guardIntervalCap;
+
+    /**
+     * Time Interleave Mode Type defined by FrontendDtmbTimeInterleaveMode.
+     */
+    int interleaveModeCap;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbCodeRate.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbCodeRate.aidl
new file mode 100644
index 0000000..7b4a438
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbCodeRate.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * CODERATE Type for DTMB.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDtmbCodeRate {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set code rate automatically
+     */
+    AUTO = 1 << 0,
+
+    CODERATE_2_5 = 1 << 1,
+
+    CODERATE_3_5 = 1 << 2,
+
+    CODERATE_4_5 = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbGuardInterval.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbGuardInterval.aidl
new file mode 100644
index 0000000..3c2e06a
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbGuardInterval.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Guard Interval Type for DTMB.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDtmbGuardInterval {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Guard Interval automatically
+     */
+    AUTO = 1 << 0,
+
+    PN_420_VARIOUS = 1 << 1,
+
+    PN_595_CONST = 1 << 2,
+
+    PN_945_VARIOUS = 1 << 3,
+
+    PN_420_CONST = 1 << 4,
+
+    PN_945_CONST = 1 << 5,
+
+    PN_RESERVED = 1 << 6,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbModulation.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbModulation.aidl
new file mode 100644
index 0000000..87bd8da
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbModulation.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Frontend Modulation Type for DTMB.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDtmbModulation {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Constellation automatically
+     */
+    AUTO = 1 << 0,
+
+    CONSTELLATION_4QAM = 1 << 1,
+
+    CONSTELLATION_4QAM_NR = 1 << 2,
+
+    CONSTELLATION_16QAM = 1 << 3,
+
+    CONSTELLATION_32QAM = 1 << 4,
+
+    CONSTELLATION_64QAM = 1 << 5,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbSettings.aidl
new file mode 100644
index 0000000..095d0b5
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbSettings.aidl
@@ -0,0 +1,56 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendDtmbBandwidth;
+import android.hardware.tv.tuner.FrontendDtmbCodeRate;
+import android.hardware.tv.tuner.FrontendDtmbGuardInterval;
+import android.hardware.tv.tuner.FrontendDtmbModulation;
+import android.hardware.tv.tuner.FrontendDtmbTimeInterleaveMode;
+import android.hardware.tv.tuner.FrontendDtmbTransmissionMode;
+import android.hardware.tv.tuner.FrontendSpectralInversion;
+
+/**
+ * Signal Setting for DTMB Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendDtmbSettings {
+    /**
+     * Signal frequency in Hertz
+     */
+    long frequency;
+
+    /**
+     * Signal end frequency in Hertz used by scan
+     */
+    long endFrequency;
+
+    FrontendSpectralInversion inversion = FrontendSpectralInversion.UNDEFINED;
+
+    FrontendDtmbTransmissionMode transmissionMode = FrontendDtmbTransmissionMode.UNDEFINED;
+
+    FrontendDtmbBandwidth bandwidth = FrontendDtmbBandwidth.UNDEFINED;
+
+    FrontendDtmbModulation modulation = FrontendDtmbModulation.UNDEFINED;
+
+    FrontendDtmbCodeRate codeRate = FrontendDtmbCodeRate.UNDEFINED;
+
+    FrontendDtmbGuardInterval guardInterval = FrontendDtmbGuardInterval.UNDEFINED;
+
+    FrontendDtmbTimeInterleaveMode interleaveMode = FrontendDtmbTimeInterleaveMode.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbTimeInterleaveMode.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbTimeInterleaveMode.aidl
new file mode 100644
index 0000000..a992524
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbTimeInterleaveMode.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Time Interleave Mode Type for DTMB.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDtmbTimeInterleaveMode {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set time interleave mode automatically
+     */
+    AUTO = 1 << 0,
+
+    TIMER_INT_240 = 1 << 1,
+
+    TIMER_INT_720 = 1 << 2,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbTransmissionMode.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbTransmissionMode.aidl
new file mode 100644
index 0000000..7ebed84
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDtmbTransmissionMode.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Transmission Mode for DTMB.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDtmbTransmissionMode {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Transmission Mode automatically
+     */
+    AUTO = 1 << 0,
+
+    C1 = 1 << 1,
+
+    C3780 = 1 << 2,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcAnnex.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcAnnex.aidl
new file mode 100644
index 0000000..3d99cee
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcAnnex.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Annex Type for DVBC.
+ * @hide
+ */
+@VintfStability
+@Backing(type="byte")
+enum FrontendDvbcAnnex {
+    UNDEFINED = 0,
+
+    A = 1 << 0,
+
+    B = 1 << 1,
+
+    C = 1 << 2,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcBandwidth.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcBandwidth.aidl
new file mode 100644
index 0000000..ff921a7
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcBandwidth.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Bandwidth Type for Cable Frontend.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbcBandwidth {
+    UNDEFINED = 0,
+
+    BANDWIDTH_5MHZ = 1 << 0,
+
+    BANDWIDTH_6MHZ = 1 << 1,
+
+    BANDWIDTH_7MHZ = 1 << 2,
+
+    BANDWIDTH_8MHZ = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcCapabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcCapabilities.aidl
new file mode 100644
index 0000000..bd7f180
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcCapabilities.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Capabilities for DVBC Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendDvbcCapabilities {
+    /**
+     * Modulation Types defined by FrontendDvbcModulation.
+     */
+    int modulationCap;
+
+    /**
+     * Inner Forward Error Correction types defined by FrontendInnerFec.
+     */
+    long fecCap;
+
+    /**
+     * Annex Types defined by FrontendDvbcAnnex.
+     */
+    byte annexCap;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcModulation.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcModulation.aidl
new file mode 100644
index 0000000..3435e76
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcModulation.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Modulation Type for DVBC.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbcModulation {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Modulation automatically
+     */
+    AUTO = 1 << 0,
+
+    MOD_16QAM = 1 << 1,
+
+    MOD_32QAM = 1 << 2,
+
+    MOD_64QAM = 1 << 3,
+
+    MOD_128QAM = 1 << 4,
+
+    MOD_256QAM = 1 << 5,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcOuterFec.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcOuterFec.aidl
new file mode 100644
index 0000000..7dc3f0f
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcOuterFec.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Outer Forward Error Correction (FEC) Type for DVBC.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbcOuterFec {
+    UNDEFINED = 0,
+
+    OUTER_FEC_NONE,
+
+    OUTER_FEC_RS,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcSettings.aidl
new file mode 100644
index 0000000..51be57f
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbcSettings.aidl
@@ -0,0 +1,61 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendCableTimeInterleaveMode;
+import android.hardware.tv.tuner.FrontendDvbcAnnex;
+import android.hardware.tv.tuner.FrontendDvbcBandwidth;
+import android.hardware.tv.tuner.FrontendDvbcModulation;
+import android.hardware.tv.tuner.FrontendDvbcOuterFec;
+import android.hardware.tv.tuner.FrontendInnerFec;
+import android.hardware.tv.tuner.FrontendSpectralInversion;
+
+/**
+ * Signal Settings for an DVBC Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendDvbcSettings {
+    /**
+     * Signal frequency in Hertz
+     */
+    long frequency;
+
+    /**
+     * Signal end frequency in Hertz used by scan
+     */
+    long endFrequency;
+
+    FrontendDvbcModulation modulation = FrontendDvbcModulation.UNDEFINED;
+
+    FrontendInnerFec fec = FrontendInnerFec.FEC_UNDEFINED;
+
+    /**
+     * Symbols per second
+     */
+    int symbolRate;
+
+    FrontendDvbcOuterFec outerFec = FrontendDvbcOuterFec.UNDEFINED;
+
+    FrontendDvbcAnnex annex = FrontendDvbcAnnex.UNDEFINED;
+
+    FrontendSpectralInversion inversion = FrontendSpectralInversion.UNDEFINED;
+
+    FrontendCableTimeInterleaveMode interleaveMode = FrontendCableTimeInterleaveMode.UNDEFINED;
+
+    FrontendDvbcBandwidth bandwidth = FrontendDvbcBandwidth.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsCapabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsCapabilities.aidl
new file mode 100644
index 0000000..acff012
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsCapabilities.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Capabilities for DVBS Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendDvbsCapabilities {
+    /**
+     * Modulation Types defined by FrontendDvbsModulation..
+     */
+    int modulationCap;
+
+    /**
+     * Inner Forward Error Correction types defined by FrontendInnerFec.
+    */
+    long innerfecCap;
+
+    /**
+     * Sub standards defined by FrontendDvbsStandard.
+     */
+    byte standard;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsCodeRate.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsCodeRate.aidl
new file mode 100644
index 0000000..70ea3ab
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsCodeRate.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendInnerFec;
+
+/**
+ * Code Rate for DVBS.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendDvbsCodeRate {
+    FrontendInnerFec fec = FrontendInnerFec.FEC_UNDEFINED;
+
+    boolean isLinear;
+
+    /**
+     * true if enable short frame
+     */
+    boolean isShortFrames;
+
+    /**
+     * bits number in 1000 symbol. 0 if use the default.
+     */
+    int bitsPer1000Symbol;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsModulation.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsModulation.aidl
new file mode 100644
index 0000000..3ba4c5b
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsModulation.aidl
@@ -0,0 +1,61 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Modulation Type for DVBS.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbsModulation {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Modulation automatically
+     */
+    AUTO = 1 << 0,
+
+    MOD_QPSK = 1 << 1,
+
+    MOD_8PSK = 1 << 2,
+
+    MOD_16QAM = 1 << 3,
+
+    MOD_16PSK = 1 << 4,
+
+    MOD_32PSK = 1 << 5,
+
+    MOD_ACM = 1 << 6,
+
+    MOD_8APSK = 1 << 7,
+
+    MOD_16APSK = 1 << 8,
+
+    MOD_32APSK = 1 << 9,
+
+    MOD_64APSK = 1 << 10,
+
+    MOD_128APSK = 1 << 11,
+
+    MOD_256APSK = 1 << 12,
+
+    /**
+     * Reserved for Proprietary modulation
+     */
+    MOD_RESERVED = 1 << 13,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsPilot.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsPilot.aidl
new file mode 100644
index 0000000..625ac2d
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsPilot.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Pilot mode for DVBS.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbsPilot {
+    UNDEFINED,
+
+    ON,
+
+    OFF,
+
+    AUTO,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsRolloff.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsRolloff.aidl
new file mode 100644
index 0000000..76d0e16
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsRolloff.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Roll Off value for DVBS.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbsRolloff {
+    UNDEFINED,
+
+    ROLLOFF_0_35,
+
+    ROLLOFF_0_25,
+
+    ROLLOFF_0_20,
+
+    ROLLOFF_0_15,
+
+    ROLLOFF_0_10,
+
+    ROLLOFF_0_5,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsScanType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsScanType.aidl
new file mode 100644
index 0000000..1afbd93
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsScanType.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Scan type for a DVBS Frontend.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbsScanType {
+    UNDEFINED = 0,
+
+    DIRECT,
+
+    DISEQC,
+
+    UNICABLE,
+
+    JESS,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsSettings.aidl
new file mode 100644
index 0000000..785046b
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsSettings.aidl
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendDvbsCodeRate;
+import android.hardware.tv.tuner.FrontendDvbsModulation;
+import android.hardware.tv.tuner.FrontendDvbsPilot;
+import android.hardware.tv.tuner.FrontendDvbsRolloff;
+import android.hardware.tv.tuner.FrontendDvbsStandard;
+import android.hardware.tv.tuner.FrontendDvbsVcmMode;
+import android.hardware.tv.tuner.FrontendDvbsScanType;
+import android.hardware.tv.tuner.FrontendSpectralInversion;
+
+/**
+ * Signal Settings for an DVBS Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendDvbsSettings {
+    /**
+     * Signal frequency in Hertz
+     */
+    long frequency;
+
+    /**
+     * Signal end frequency in Hertz used by scan
+     */
+    long endFrequency;
+
+    FrontendSpectralInversion inversion = FrontendSpectralInversion.UNDEFINED;
+
+    FrontendDvbsModulation modulation = FrontendDvbsModulation.UNDEFINED;
+
+    FrontendDvbsCodeRate coderate;
+
+    /**
+     * Symbols per second
+     */
+    int symbolRate;
+
+    FrontendDvbsRolloff rolloff = FrontendDvbsRolloff.UNDEFINED;
+
+    FrontendDvbsPilot pilot = FrontendDvbsPilot.UNDEFINED;
+
+    int inputStreamId;
+
+    FrontendDvbsStandard standard = FrontendDvbsStandard.UNDEFINED;
+
+    FrontendDvbsVcmMode vcmMode = FrontendDvbsVcmMode.UNDEFINED;
+
+    FrontendDvbsScanType scanType = FrontendDvbsScanType.UNDEFINED;
+
+    boolean isDiseqcRxMessage;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsStandard.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsStandard.aidl
new file mode 100644
index 0000000..bc8e0ea
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsStandard.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Sub standards in DVBS.
+ * @hide
+ */
+@VintfStability
+@Backing(type="byte")
+enum FrontendDvbsStandard {
+    UNDEFINED = 0,
+
+    AUTO = 1 << 0,
+
+    S = 1 << 1,
+
+    S2 = 1 << 2,
+
+    S2X = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsVcmMode.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsVcmMode.aidl
new file mode 100644
index 0000000..2b41dcd
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbsVcmMode.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * VCM mode in DVBS.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbsVcmMode {
+    UNDEFINED,
+
+    AUTO,
+
+    MANUAL,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtBandwidth.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtBandwidth.aidl
new file mode 100644
index 0000000..1d31358
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtBandwidth.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Bandwidth Type for DVBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbtBandwidth {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Bandwidth automatically
+     */
+    AUTO = 1 << 0,
+
+    BANDWIDTH_8MHZ = 1 << 1,
+
+    BANDWIDTH_7MHZ = 1 << 2,
+
+    BANDWIDTH_6MHZ = 1 << 3,
+
+    BANDWIDTH_5MHZ = 1 << 4,
+
+    BANDWIDTH_1_7MHZ = 1 << 5,
+
+    BANDWIDTH_10MHZ = 1 << 6,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtCapabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtCapabilities.aidl
new file mode 100644
index 0000000..6bb473d
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtCapabilities.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Capabilities for DVBT Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendDvbtCapabilities {
+    /**
+     * Transmission Modes defined by FrontendDvbtTransmissionMode.
+     */
+    int transmissionModeCap;
+
+    /**
+     * Bandwidth Types defined by FrontendDvbtBandwidth.
+     */
+    int bandwidthCap;
+
+    /**
+     * Extended Constellations defined by FrontendDvbtConstellation.
+     */
+    int constellationCap;
+
+    /**
+     * Code Rates defined by FrontendDvbtCoderate.
+     */
+    int coderateCap;
+
+    /**
+     * Hierarchy Types defined by FrontendDvbtHierarchy.
+     */
+    int hierarchyCap;
+
+    /**
+     * Guard Interval Types defined by FrontendDvbtGuardInterval.
+     */
+    int guardIntervalCap;
+
+    boolean isT2Supported;
+
+    boolean isMisoSupported;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtCoderate.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtCoderate.aidl
new file mode 100644
index 0000000..5111003
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtCoderate.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Code Rate for DVBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbtCoderate {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Hierarchy automatically
+     */
+    AUTO = 1 << 0,
+
+    CODERATE_1_2 = 1 << 1,
+
+    CODERATE_2_3 = 1 << 2,
+
+    CODERATE_3_4 = 1 << 3,
+
+    CODERATE_5_6 = 1 << 4,
+
+    CODERATE_7_8 = 1 << 5,
+
+    CODERATE_3_5 = 1 << 6,
+
+    CODERATE_4_5 = 1 << 7,
+
+    CODERATE_6_7 = 1 << 8,
+
+    CODERATE_8_9 = 1 << 9,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtConstellation.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtConstellation.aidl
new file mode 100644
index 0000000..2680778
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtConstellation.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Extended Constellation for DVBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbtConstellation {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Constellation automatically
+     */
+    AUTO = 1 << 0,
+
+    CONSTELLATION_QPSK = 1 << 1,
+
+    CONSTELLATION_16QAM = 1 << 2,
+
+    CONSTELLATION_64QAM = 1 << 3,
+
+    CONSTELLATION_256QAM = 1 << 4,
+
+    CONSTELLATION_QPSK_R = 1 << 5,
+
+    CONSTELLATION_16QAM_R = 1 << 6,
+
+    CONSTELLATION_64QAM_R = 1 << 7,
+
+    CONSTELLATION_256QAM_R = 1 << 8,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtGuardInterval.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtGuardInterval.aidl
new file mode 100644
index 0000000..8d60b2f
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtGuardInterval.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Guard Interval Type for DVBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbtGuardInterval {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Guard Interval automatically
+     */
+    AUTO = 1 << 0,
+
+    INTERVAL_1_32 = 1 << 1,
+
+    INTERVAL_1_16 = 1 << 2,
+
+    INTERVAL_1_8 = 1 << 3,
+
+    INTERVAL_1_4 = 1 << 4,
+
+    INTERVAL_1_128 = 1 << 5,
+
+    INTERVAL_19_128 = 1 << 6,
+
+    INTERVAL_19_256 = 1 << 7,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtHierarchy.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtHierarchy.aidl
new file mode 100644
index 0000000..859c760
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtHierarchy.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Hierarchy Type for DVBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbtHierarchy {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Hierarchy automatically
+     */
+    AUTO = 1 << 0,
+
+    HIERARCHY_NON_NATIVE = 1 << 1,
+
+    HIERARCHY_1_NATIVE = 1 << 2,
+
+    HIERARCHY_2_NATIVE = 1 << 3,
+
+    HIERARCHY_4_NATIVE = 1 << 4,
+
+    HIERARCHY_NON_INDEPTH = 1 << 5,
+
+    HIERARCHY_1_INDEPTH = 1 << 6,
+
+    HIERARCHY_2_INDEPTH = 1 << 7,
+
+    HIERARCHY_4_INDEPTH = 1 << 8,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtPlpMode.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtPlpMode.aidl
new file mode 100644
index 0000000..fa70cc7
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtPlpMode.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Physical Layer Pipe (PLP) Mode for DVBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbtPlpMode {
+    UNDEFINED,
+
+    AUTO,
+
+    MANUAL,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtSettings.aidl
new file mode 100644
index 0000000..238f071
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtSettings.aidl
@@ -0,0 +1,84 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendDvbtBandwidth;
+import android.hardware.tv.tuner.FrontendDvbtCoderate;
+import android.hardware.tv.tuner.FrontendDvbtConstellation;
+import android.hardware.tv.tuner.FrontendDvbtGuardInterval;
+import android.hardware.tv.tuner.FrontendDvbtHierarchy;
+import android.hardware.tv.tuner.FrontendDvbtPlpMode;
+import android.hardware.tv.tuner.FrontendDvbtStandard;
+import android.hardware.tv.tuner.FrontendDvbtTransmissionMode;
+import android.hardware.tv.tuner.FrontendSpectralInversion;
+
+/**
+ * Signal Settings for DVBT Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendDvbtSettings {
+    /**
+     * Signal frequency in Hertz
+     */
+    long frequency;
+
+    /**
+     * Signal end frequency in Hertz used by scan
+     */
+    long endFrequency;
+
+    FrontendSpectralInversion inversion = FrontendSpectralInversion.UNDEFINED;
+
+    FrontendDvbtTransmissionMode transmissionMode = FrontendDvbtTransmissionMode.UNDEFINED;
+
+    FrontendDvbtBandwidth bandwidth = FrontendDvbtBandwidth.UNDEFINED;
+
+    FrontendDvbtConstellation constellation = FrontendDvbtConstellation.UNDEFINED;
+
+    FrontendDvbtHierarchy hierarchy = FrontendDvbtHierarchy.UNDEFINED;
+
+    /**
+     * Code Rate for High Priority level
+     */
+    FrontendDvbtCoderate hpCoderate = FrontendDvbtCoderate.UNDEFINED;
+
+    /**
+     * Code Rate for Low Priority level
+     */
+    FrontendDvbtCoderate lpCoderate = FrontendDvbtCoderate.UNDEFINED;
+
+    FrontendDvbtGuardInterval guardInterval = FrontendDvbtGuardInterval.UNDEFINED;
+
+    boolean isHighPriority;
+
+    FrontendDvbtStandard standard = FrontendDvbtStandard.UNDEFINED;
+
+    boolean isMiso;
+
+    FrontendDvbtPlpMode plpMode = FrontendDvbtPlpMode.UNDEFINED;
+
+    /**
+     * Physical Layer Pipe (PLP) Id
+     */
+    int plpId;
+
+    /**
+     * Group Id for Physical Layer Pipe (PLP)
+     */
+    int plpGroupId;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtStandard.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtStandard.aidl
new file mode 100644
index 0000000..bf18618
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtStandard.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Sub standards in DVBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="byte")
+enum FrontendDvbtStandard {
+    UNDEFINED = 0,
+
+    AUTO = 1 << 0,
+
+    T = 1 << 1,
+
+    T2 = 1 << 2,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.aidl
new file mode 100644
index 0000000..ef2ceef
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Extended Transmission Mode for DVBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendDvbtTransmissionMode {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Transmission Mode automatically
+     */
+    AUTO = 1 << 0,
+
+    MODE_2K = 1 << 1,
+
+    MODE_8K = 1 << 2,
+
+    MODE_4K = 1 << 3,
+
+    MODE_1K = 1 << 4,
+
+    MODE_16K = 1 << 5,
+
+    MODE_32K = 1 << 6,
+
+    MODE_8K_E = 1 << 7,
+
+    MODE_16K_E = 1 << 8,
+
+    MODE_32K_E = 1 << 9,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendEventType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendEventType.aidl
new file mode 100644
index 0000000..501dc1f
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendEventType.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Frontend Event Type.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendEventType {
+    /**
+     * The frontend has locked to the signal specified by the tune method. It can also be notified
+     * after signal is locked if the signal attributes transmission parameter of the signal is
+     * changed (e.g., Modulation).
+     */
+    LOCKED,
+
+    /**
+     * The frontend is unable to lock to the signal specified by the tune method.
+     */
+    NO_SIGNAL,
+
+    /**
+     * The frontend has lost the lock to the signal specified by the tune method.
+     */
+    LOST_LOCK,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendGuardInterval.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendGuardInterval.aidl
new file mode 100644
index 0000000..cf82921
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendGuardInterval.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendDvbtGuardInterval;
+import android.hardware.tv.tuner.FrontendDtmbGuardInterval;
+import android.hardware.tv.tuner.FrontendIsdbtGuardInterval;
+
+/**
+ * The different Guard Interval Types.
+ * @hide
+ */
+@VintfStability
+union FrontendGuardInterval {
+    FrontendDvbtGuardInterval dvbt = FrontendDvbtGuardInterval.UNDEFINED;
+
+    FrontendIsdbtGuardInterval isdbt;
+
+    FrontendDtmbGuardInterval dtmb;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendInfo.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendInfo.aidl
new file mode 100644
index 0000000..6168fc1
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendInfo.aidl
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendCapabilities;
+import android.hardware.tv.tuner.FrontendStatusType;
+import android.hardware.tv.tuner.FrontendType;
+
+/**
+ * Information for the Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendInfo {
+    FrontendType type = FrontendType.UNDEFINED;
+
+    /**
+     * Frequency in Hertz
+     */
+    long minFrequency;
+
+    /**
+     * Frequency in Hertz
+     */
+    long maxFrequency;
+
+    /**
+     * Minimum symbols per second
+     */
+    int minSymbolRate;
+
+    /**
+     * Maximum symbols per second
+     */
+    int maxSymbolRate;
+
+    /**
+     * Range in Hertz
+     */
+    long acquireRange;
+
+    /**
+     * Frontends are assigned with the same exclusiveGroupId if they can't
+     * function at same time. For instance, they share same hardware module.
+     */
+    int exclusiveGroupId;
+
+    /**
+     * A list of supported status types which client can inquiry
+     */
+    FrontendStatusType[] statusCaps;
+
+    FrontendCapabilities frontendCaps;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendInnerFec.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendInnerFec.aidl
new file mode 100644
index 0000000..b94af4b
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendInnerFec.aidl
@@ -0,0 +1,296 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Inner Forward Error Correction type as specified in ETSI EN 300 468 V1.15.1
+ * and ETSI EN 302 307-2 V1.1.1.
+ * @hide
+ */
+@VintfStability
+@Backing(type="long")
+enum FrontendInnerFec {
+    /**
+     * Not defined
+     */
+    FEC_UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set FEC automatically
+     */
+    AUTO = 1L << 0,
+
+    /**
+     * 1/2 conv. code rate
+     */
+    FEC_1_2 = 1L << 1,
+
+    /**
+     * 1/3 conv. code rate
+     */
+    FEC_1_3 = 1L << 2,
+
+    /**
+     * 1/4 conv. code rate
+     */
+    FEC_1_4 = 1L << 3,
+
+    /**
+     * 1/5 conv. code rate
+     */
+    FEC_1_5 = 1L << 4,
+
+    /**
+     * 2/3 conv. code rate
+     */
+    FEC_2_3 = 1L << 5,
+
+    /**
+     * 2/5 conv. code rate
+     */
+    FEC_2_5 = 1L << 6,
+
+    /**
+     * 2/9 conv. code rate
+     */
+    FEC_2_9 = 1L << 7,
+
+    /**
+     * 3/4 conv. code rate
+     */
+    FEC_3_4 = 1L << 8,
+
+    /**
+     * 3/5 conv. code rate
+     */
+    FEC_3_5 = 1L << 9,
+
+    /**
+     * 4/5 conv. code rate
+     */
+    FEC_4_5 = 1L << 10,
+
+    /**
+     * 4/15 conv. code rate
+     */
+    FEC_4_15 = 1L << 11,
+
+    /**
+     * 5/6 conv. code rate
+     */
+    FEC_5_6 = 1L << 12,
+
+    /**
+     * 5/9 conv. code rate
+     */
+    FEC_5_9 = 1L << 13,
+
+    /**
+     * 6/7 conv. code rate
+     */
+    FEC_6_7 = 1L << 14,
+
+    /**
+     * 7/8 conv. code rate
+     */
+    FEC_7_8 = 1L << 15,
+
+    /**
+     * 7/9 conv. code rate
+     */
+    FEC_7_9 = 1L << 16,
+
+    /**
+     * 7/15 conv. code rate
+     */
+    FEC_7_15 = 1L << 17,
+
+    /**
+     * 8/9 conv. code rate
+     */
+    FEC_8_9 = 1L << 18,
+
+    /**
+     * 8/15 conv. code rate
+     */
+    FEC_8_15 = 1L << 19,
+
+    /**
+     * 9/10 conv. code rate
+     */
+    FEC_9_10 = 1L << 20,
+
+    /**
+     * 9/20 conv. code rate
+     */
+    FEC_9_20 = 1L << 21,
+
+    /**
+     * 11/15 conv. code rate
+     */
+    FEC_11_15 = 1L << 22,
+
+    /**
+     * 11/20 conv. code rate
+     */
+    FEC_11_20 = 1L << 23,
+
+    /**
+     * 11/45 conv. code rate
+     */
+    FEC_11_45 = 1L << 24,
+
+    /**
+     * 13/18 conv. code rate
+     */
+    FEC_13_18 = 1L << 25,
+
+    /**
+     * 13/45 conv. code rate
+     */
+    FEC_13_45 = 1L << 26,
+
+    /**
+     * 14/45 conv. code rate
+     */
+    FEC_14_45 = 1L << 27,
+
+    /**
+     * 23/36 conv. code rate
+     */
+    FEC_23_36 = 1L << 28,
+
+    /**
+     * 25/36 conv. code rate
+     */
+    FEC_25_36 = 1L << 29,
+
+    /**
+     * 26/45 conv. code rate
+     */
+    FEC_26_45 = 1L << 30,
+
+    /**
+     * 28/45 conv. code rate
+     */
+    FEC_28_45 = 1L << 31,
+
+    /**
+     * 29/45 conv. code rate
+     */
+    FEC_29_45 = 1L << 32,
+
+    /**
+     * 31/45 conv. code rate
+     */
+    FEC_31_45 = 1L << 33,
+
+    /**
+     * 32/45 conv. code rate
+     */
+    FEC_32_45 = 1L << 34,
+
+    /**
+     * 77/90 conv. code rate
+     */
+    FEC_77_90 = 1L << 35,
+
+    /**
+     * 2/15 conv. code rate
+     */
+    FEC_2_15 = 1L << 36,
+
+    /**
+     * 3/15 conv. code rate
+     */
+    FEC_3_15 = 1L << 37,
+
+    /**
+     * 5/15 conv. code rate
+     */
+    FEC_5_15 = 1L << 38,
+
+    /**
+     * 6/15 conv. code rate
+     */
+    FEC_6_15 = 1L << 39,
+
+    /**
+     * 9/15 conv. code rate
+     */
+    FEC_9_15 = 1L << 40,
+
+    /**
+     * 10/15 conv. code rate
+     */
+    FEC_10_15 = 1L << 41,
+
+    /**
+     * 12/15 conv. code rate
+     */
+    FEC_12_15 = 1L << 42,
+
+    /**
+     * 13/15 conv. code rate
+     */
+    FEC_13_15 = 1L << 43,
+
+    /**
+     * 18/30 conv. code rate
+     */
+    FEC_18_30 = 1L << 44,
+
+    /**
+     * 20/30 conv. code rate
+     */
+    FEC_20_30 = 1L << 45,
+
+    /**
+     * 90/180 conv. code rate
+     */
+    FEC_90_180 = 1L << 46,
+
+    /**
+     * 96/180 conv. code rate
+     */
+    FEC_96_180 = 1L << 47,
+
+    /**
+     * 104/180 conv. code rate
+     */
+    FEC_104_180 = 1L << 48,
+
+    /**
+     * 128/180 conv. code rate
+     */
+    FEC_128_180 = 1L << 49,
+
+    /**
+     * 132/180 conv. code rate
+     */
+    FEC_132_180 = 1L << 50,
+
+    /**
+     * 135/180 conv. code rate
+     */
+    FEC_135_180 = 1L << 51,
+
+    /**
+     * 140/180 conv. code rate
+     */
+    FEC_140_180 = 1L << 52,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendInterleaveMode.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendInterleaveMode.aidl
new file mode 100644
index 0000000..106ef67
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendInterleaveMode.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAtsc3TimeInterleaveMode;
+import android.hardware.tv.tuner.FrontendCableTimeInterleaveMode;
+import android.hardware.tv.tuner.FrontendDtmbTimeInterleaveMode;
+import android.hardware.tv.tuner.FrontendIsdbtTimeInterleaveMode;
+
+/**
+ * @hide
+ */
+@VintfStability
+union FrontendInterleaveMode {
+    FrontendAtsc3TimeInterleaveMode atsc3
+        = FrontendAtsc3TimeInterleaveMode.UNDEFINED;
+
+    FrontendCableTimeInterleaveMode dvbc;
+
+    FrontendDtmbTimeInterleaveMode dtmb;
+
+    FrontendIsdbtTimeInterleaveMode isdbt;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Capabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Capabilities.aidl
new file mode 100644
index 0000000..a98e1b3
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Capabilities.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Capabilities for ISDBS3 Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendIsdbs3Capabilities {
+    /**
+     * Modulaltion Types defined by FrontendIsdbs3Modulation.
+     */
+    int modulationCap;
+
+    /**
+     * Code Rate Types defined by FrontendIsdbs3Coderate.
+     */
+    int coderateCap;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Coderate.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Coderate.aidl
new file mode 100644
index 0000000..9e36c1e
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Coderate.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Code Rate Type for ISDBS3.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbs3Coderate {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Code Rate automatically
+     */
+    AUTO = 1 << 0,
+
+    CODERATE_1_3 = 1 << 1,
+
+    CODERATE_2_5 = 1 << 2,
+
+    CODERATE_1_2 = 1 << 3,
+
+    CODERATE_3_5 = 1 << 4,
+
+    CODERATE_2_3 = 1 << 5,
+
+    CODERATE_3_4 = 1 << 6,
+
+    CODERATE_7_9 = 1 << 7,
+
+    CODERATE_4_5 = 1 << 8,
+
+    CODERATE_5_6 = 1 << 9,
+
+    CODERATE_7_8 = 1 << 10,
+
+    CODERATE_9_10 = 1 << 11,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Modulation.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Modulation.aidl
new file mode 100644
index 0000000..5041f63
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Modulation.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Modulaltion Type for ISDBS3.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbs3Modulation {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Modulation automatically
+     */
+    AUTO = 1 << 0,
+
+    MOD_BPSK = 1 << 1,
+
+    MOD_QPSK = 1 << 2,
+
+    MOD_8PSK = 1 << 3,
+
+    MOD_16APSK = 1 << 4,
+
+    MOD_32APSK = 1 << 5,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Rolloff.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Rolloff.aidl
new file mode 100644
index 0000000..bdef4d7
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Rolloff.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Roll of Type for ISDBS3.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbs3Rolloff {
+    UNDEFINED,
+
+    ROLLOFF_0_03,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Settings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Settings.aidl
new file mode 100644
index 0000000..9b38a59
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbs3Settings.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendIsdbs3Coderate;
+import android.hardware.tv.tuner.FrontendIsdbs3Modulation;
+import android.hardware.tv.tuner.FrontendIsdbs3Rolloff;
+import android.hardware.tv.tuner.FrontendIsdbsStreamIdType;
+
+/**
+ * Signal Settings for ISDBS3 Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendIsdbs3Settings {
+    /**
+     * Signal frequency in Hertz
+     */
+    long frequency;
+
+    /**
+     * Signal end frequency in Hertz used by scan
+     */
+    long endFrequency;
+
+    int streamId;
+
+    FrontendIsdbsStreamIdType streamIdType = FrontendIsdbsStreamIdType.UNDEFINED;
+
+    FrontendIsdbs3Modulation modulation = FrontendIsdbs3Modulation.UNDEFINED;
+
+    FrontendIsdbs3Coderate coderate = FrontendIsdbs3Coderate.UNDEFINED;
+
+    /**
+     * Symbols per second
+     */
+    int symbolRate;
+
+    FrontendIsdbs3Rolloff rolloff = FrontendIsdbs3Rolloff.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsCapabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsCapabilities.aidl
new file mode 100644
index 0000000..842609e
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsCapabilities.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Capabilities for ISDBS Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendIsdbsCapabilities {
+    /**
+     * Modulation Types defined by FrontendIsdbsModulation.
+     */
+    int modulationCap;
+
+    /**
+     * Code Rates defined by FrontendIsdbsCoderate.
+     */
+    int coderateCap;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsCoderate.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsCoderate.aidl
new file mode 100644
index 0000000..afcb05e
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsCoderate.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Code Rate Type for ISDBS.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbsCoderate {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Code Rate automatically
+     */
+    AUTO = 1 << 0,
+
+    CODERATE_1_2 = 1 << 1,
+
+    CODERATE_2_3 = 1 << 2,
+
+    CODERATE_3_4 = 1 << 3,
+
+    CODERATE_5_6 = 1 << 4,
+
+    CODERATE_7_8 = 1 << 5,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsModulation.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsModulation.aidl
new file mode 100644
index 0000000..051580c
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsModulation.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Modulation Type for ISDBS.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbsModulation {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Modulation automatically
+     */
+    AUTO = 1 << 0,
+
+    MOD_BPSK = 1 << 1,
+
+    MOD_QPSK = 1 << 2,
+
+    MOD_TC8PSK = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsRolloff.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsRolloff.aidl
new file mode 100644
index 0000000..961f16b
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsRolloff.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Roll Off Type for ISDBS.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbsRolloff {
+    UNDEFINED,
+
+    ROLLOFF_0_35,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsSettings.aidl
new file mode 100644
index 0000000..d5b90b7
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsSettings.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendIsdbsCoderate;
+import android.hardware.tv.tuner.FrontendIsdbsModulation;
+import android.hardware.tv.tuner.FrontendIsdbsRolloff;
+import android.hardware.tv.tuner.FrontendIsdbsStreamIdType;
+
+/**
+ * Signal Settings for ISDBS Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendIsdbsSettings {
+    /**
+     * Signal frequency in Hertz
+     */
+    long frequency;
+
+    /**
+     * Signal end frequency in Hertz used by scan
+     */
+    long endFrequency;
+
+    int streamId;
+
+    FrontendIsdbsStreamIdType streamIdType = FrontendIsdbsStreamIdType.UNDEFINED;
+
+    FrontendIsdbsModulation modulation = FrontendIsdbsModulation.UNDEFINED;
+
+    FrontendIsdbsCoderate coderate = FrontendIsdbsCoderate.UNDEFINED;
+
+    /**
+     * Symbols per second
+     */
+    int symbolRate;
+
+    FrontendIsdbsRolloff rolloff = FrontendIsdbsRolloff.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsStreamIdType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsStreamIdType.aidl
new file mode 100644
index 0000000..66b5694
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbsStreamIdType.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Stream Id Type for ISDBS.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbsStreamIdType {
+    STREAM_ID,
+
+    RELATIVE_STREAM_NUMBER,
+
+    UNDEFINED,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtBandwidth.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtBandwidth.aidl
new file mode 100644
index 0000000..f4a1450
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtBandwidth.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Bandwidth for ISDBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbtBandwidth {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Bandwidth automatically
+     */
+    AUTO = 1 << 0,
+
+    BANDWIDTH_8MHZ = 1 << 1,
+
+    BANDWIDTH_7MHZ = 1 << 2,
+
+    BANDWIDTH_6MHZ = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtCapabilities.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtCapabilities.aidl
new file mode 100644
index 0000000..b2bdfd4
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtCapabilities.aidl
@@ -0,0 +1,64 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Capabilities for ISDBT Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendIsdbtCapabilities {
+    /**
+     * Modes defined by FrontendIsdbtMode.
+     */
+    int modeCap;
+
+    /**
+     * Bandwidths defined by FrontendIsdbtBandwidth.
+     */
+    int bandwidthCap;
+
+    /**
+     * Modulations defined by FrontendIsdbtModulation.
+     */
+    int modulationCap;
+
+    /**
+     * Code Rates defined by FrontendIsdbtCoderate.
+     */
+    int coderateCap;
+
+    /**
+     * Guard Interval Types defined by FrontendIsdbtGuardInterval.
+     */
+    int guardIntervalCap;
+
+    /**
+     * Time Interleaves defined by FrontendIsdbtTimeInterleaveMode.
+     */
+    int timeInterleaveCap;
+
+    /**
+     * If segment auto Supported or not.
+     */
+    boolean isSegmentAuto;
+
+    /**
+     * If full segment supported or not.
+     */
+    boolean isFullSegment;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtCoderate.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtCoderate.aidl
new file mode 100644
index 0000000..ee229c5
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtCoderate.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Code Rate for ISDBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbtCoderate {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Hierarchy automatically
+     */
+    AUTO = 1 << 0,
+
+    CODERATE_1_2 = 1 << 1,
+
+    CODERATE_2_3 = 1 << 2,
+
+    CODERATE_3_4 = 1 << 3,
+
+    CODERATE_5_6 = 1 << 4,
+
+    CODERATE_7_8 = 1 << 5,
+
+    CODERATE_3_5 = 1 << 6,
+
+    CODERATE_4_5 = 1 << 7,
+
+    CODERATE_6_7 = 1 << 8,
+
+    CODERATE_8_9 = 1 << 9,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtGuardInterval.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtGuardInterval.aidl
new file mode 100644
index 0000000..a3540dc
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtGuardInterval.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Guard Interval Type for ISDBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbtGuardInterval {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Guard Interval automatically
+     */
+    AUTO = 1 << 0,
+
+    INTERVAL_1_32 = 1 << 1,
+
+    INTERVAL_1_16 = 1 << 2,
+
+    INTERVAL_1_8 = 1 << 3,
+
+    INTERVAL_1_4 = 1 << 4,
+
+    INTERVAL_1_128 = 1 << 5,
+
+    INTERVAL_19_128 = 1 << 6,
+
+    INTERVAL_19_256 = 1 << 7,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtLayerSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtLayerSettings.aidl
new file mode 100644
index 0000000..0b44ecb
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtLayerSettings.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendIsdbtCoderate;
+import android.hardware.tv.tuner.FrontendIsdbtModulation;
+import android.hardware.tv.tuner.FrontendIsdbtTimeInterleaveMode;
+
+/**
+ * Layer Settings for ISDB-T Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendIsdbtLayerSettings {
+    FrontendIsdbtModulation modulation = FrontendIsdbtModulation.UNDEFINED;
+
+    FrontendIsdbtCoderate coderate = FrontendIsdbtCoderate.UNDEFINED;
+
+    FrontendIsdbtTimeInterleaveMode timeInterleave = FrontendIsdbtTimeInterleaveMode.UNDEFINED;
+
+    /**
+     * 0 ~ 13 and 0xFF(Auto)
+     */
+    int numOfSegment;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtMode.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtMode.aidl
new file mode 100644
index 0000000..1a130fb
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtMode.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Mode for ISDBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbtMode {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Mode automatically
+     */
+    AUTO = 1 << 0,
+
+    MODE_1 = 1 << 1,
+
+    MODE_2 = 1 << 2,
+
+    MODE_3 = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtModulation.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtModulation.aidl
new file mode 100644
index 0000000..b94f578
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtModulation.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Modulation for ISDBT.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbtModulation {
+    UNDEFINED = 0,
+
+    /**
+     * hardware is able to detect and set Modulation automatically
+     */
+    AUTO = 1 << 0,
+
+    MOD_DQPSK = 1 << 1,
+
+    MOD_QPSK = 1 << 2,
+
+    MOD_16QAM = 1 << 3,
+
+    MOD_64QAM = 1 << 4,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtPartialReceptionFlag.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtPartialReceptionFlag.aidl
new file mode 100644
index 0000000..81c28cd
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtPartialReceptionFlag.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Partial Reception Flag for an ISTB-T Frontend.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbtPartialReceptionFlag {
+    UNDEFINED = 0,
+
+    /**
+     * Hardware is able to detect and set Partial Reception Flag automatically.
+     */
+    AUTO = 1 << 0,
+
+    FALSE = 1 << 1,
+
+    TRUE = 1 << 2,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtSettings.aidl
new file mode 100644
index 0000000..23a4769
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtSettings.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendIsdbtBandwidth;
+import android.hardware.tv.tuner.FrontendIsdbtGuardInterval;
+import android.hardware.tv.tuner.FrontendIsdbtLayerSettings;
+import android.hardware.tv.tuner.FrontendIsdbtMode;
+import android.hardware.tv.tuner.FrontendIsdbtPartialReceptionFlag;
+import android.hardware.tv.tuner.FrontendSpectralInversion;
+
+/**
+ * Signal Settings for ISDBT Frontend.
+ * @hide
+ */
+@VintfStability
+parcelable FrontendIsdbtSettings {
+    /**
+     * Signal frequency in Hertz
+     */
+    long frequency;
+
+    /**
+     * Signal end frequency in Hertz used by scan
+     */
+    long endFrequency;
+
+    FrontendSpectralInversion inversion = FrontendSpectralInversion.UNDEFINED;
+
+    FrontendIsdbtBandwidth bandwidth = FrontendIsdbtBandwidth.UNDEFINED;
+
+    FrontendIsdbtMode mode = FrontendIsdbtMode.UNDEFINED;
+
+    FrontendIsdbtGuardInterval guardInterval = FrontendIsdbtGuardInterval.UNDEFINED;
+
+    int serviceAreaId;
+
+    FrontendIsdbtPartialReceptionFlag partialReceptionFlag = FrontendIsdbtPartialReceptionFlag.UNDEFINED;
+
+    FrontendIsdbtLayerSettings[] layerSettings;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.aidl
new file mode 100644
index 0000000..6192fca
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.aidl
@@ -0,0 +1,56 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Time Interleave Mode for ISDB-T Frontend.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendIsdbtTimeInterleaveMode {
+    UNDEFINED = 0,
+
+    /**
+     * Hardware is able to detect and set Time Interleave Mode automatically.
+     */
+    AUTO = 1 << 0,
+
+    INTERLEAVE_1_0 = 1 << 1,
+
+    INTERLEAVE_1_4 = 1 << 2,
+
+    INTERLEAVE_1_8 = 1 << 3,
+
+    INTERLEAVE_1_16 = 1 << 4,
+
+    INTERLEAVE_2_0 = 1 << 5,
+
+    INTERLEAVE_2_2 = 1 << 6,
+
+    INTERLEAVE_2_4 = 1 << 7,
+
+    INTERLEAVE_2_8 = 1 << 8,
+
+    INTERLEAVE_3_0 = 1 << 9,
+
+    INTERLEAVE_3_1 = 1 << 10,
+
+    INTERLEAVE_3_2 = 1 << 11,
+
+    INTERLEAVE_3_4 = 1 << 12,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendModulation.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendModulation.aidl
new file mode 100644
index 0000000..dd09ff6
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendModulation.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAtsc3Modulation;
+import android.hardware.tv.tuner.FrontendAtscModulation;
+import android.hardware.tv.tuner.FrontendDvbcModulation;
+import android.hardware.tv.tuner.FrontendDvbsModulation;
+import android.hardware.tv.tuner.FrontendIsdbs3Modulation;
+import android.hardware.tv.tuner.FrontendIsdbsModulation;
+import android.hardware.tv.tuner.FrontendIsdbtModulation;
+import android.hardware.tv.tuner.FrontendDtmbModulation;
+import android.hardware.tv.tuner.FrontendDvbtConstellation;
+
+/**
+ * @hide
+ */
+@VintfStability
+union FrontendModulation {
+    FrontendDvbcModulation dvbc = FrontendDvbcModulation.UNDEFINED;
+
+    FrontendDvbsModulation dvbs;
+
+    FrontendDvbtConstellation dvbt;
+
+    FrontendIsdbsModulation isdbs;
+
+    FrontendIsdbs3Modulation isdbs3;
+
+    FrontendIsdbtModulation isdbt;
+
+    FrontendAtscModulation atsc;
+
+    FrontendAtsc3Modulation atsc3;
+
+    FrontendDtmbModulation dtmb;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendModulationStatus.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendModulationStatus.aidl
new file mode 100644
index 0000000..8630c7d
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendModulationStatus.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendDvbcModulation;
+import android.hardware.tv.tuner.FrontendDvbsModulation;
+import android.hardware.tv.tuner.FrontendIsdbs3Modulation;
+import android.hardware.tv.tuner.FrontendIsdbsModulation;
+import android.hardware.tv.tuner.FrontendIsdbtModulation;
+
+/**
+ * Modulation Type for Frontend's status.
+ * @hide
+ */
+@VintfStability
+union FrontendModulationStatus {
+    FrontendDvbcModulation dvbc = FrontendDvbcModulation.UNDEFINED;
+
+    FrontendDvbsModulation dvbs;
+
+    FrontendIsdbsModulation isdbs;
+
+    FrontendIsdbs3Modulation isdbs3;
+
+    FrontendIsdbtModulation isdbt;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendRollOff.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendRollOff.aidl
new file mode 100644
index 0000000..2b8e887
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendRollOff.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendDvbsRolloff;
+import android.hardware.tv.tuner.FrontendIsdbs3Rolloff;
+import android.hardware.tv.tuner.FrontendIsdbsRolloff;
+
+/**
+ * @hide
+ */
+@VintfStability
+union FrontendRollOff {
+    FrontendDvbsRolloff dvbs = FrontendDvbsRolloff.UNDEFINED;
+
+    FrontendIsdbsRolloff isdbs;
+
+    FrontendIsdbs3Rolloff isdbs3;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanAtsc3PlpInfo.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanAtsc3PlpInfo.aidl
new file mode 100644
index 0000000..ac0c287
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanAtsc3PlpInfo.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * ATSC3.0 PLP information for scan
+ * @hide
+ */
+@VintfStability
+parcelable FrontendScanAtsc3PlpInfo {
+    int plpId;
+
+    boolean bLlsFlag;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanMessage.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanMessage.aidl
new file mode 100644
index 0000000..a941066
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanMessage.aidl
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAnalogType;
+import android.hardware.tv.tuner.FrontendDvbcAnnex;
+import android.hardware.tv.tuner.FrontendDvbtHierarchy;
+import android.hardware.tv.tuner.FrontendModulation;
+import android.hardware.tv.tuner.FrontendScanAtsc3PlpInfo;
+import android.hardware.tv.tuner.FrontendScanMessageStandard;
+
+/**
+ * Scan Message for Frontend.
+ * @hide
+ */
+@VintfStability
+union FrontendScanMessage {
+    boolean isLocked;
+
+    boolean isEnd;
+
+    /**
+     * scan progress percent (0..100)
+     */
+    int progressPercent;
+
+    /**
+     * Signal frequencies in Hertz
+     */
+    long[] frequencies;
+
+    /**
+     * Symbols per second
+     */
+    int[] symbolRates;
+
+    FrontendDvbtHierarchy hierarchy;
+
+    FrontendAnalogType analogType;
+
+    int[] plpIds;
+
+    int[] groupIds;
+
+    int[] inputStreamIds;
+
+    FrontendScanMessageStandard std;
+
+    /**
+     * A list of PLP status in a tuned frequency band for ATSC3 frontend.
+     */
+    FrontendScanAtsc3PlpInfo[] atsc3PlpInfos;
+
+    FrontendModulation modulation;
+
+    FrontendDvbcAnnex annex;
+
+    boolean isHighPriority;
+
+    /**
+     * DVB-T Cell Ids.
+     */
+    int[] dvbtCellIds;
+
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanMessageStandard.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanMessageStandard.aidl
new file mode 100644
index 0000000..9df725e
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanMessageStandard.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAnalogSifStandard;
+import android.hardware.tv.tuner.FrontendDvbsStandard;
+import android.hardware.tv.tuner.FrontendDvbtStandard;
+
+/**
+ * @hide
+ */
+@VintfStability
+union FrontendScanMessageStandard {
+    FrontendDvbsStandard sStd = FrontendDvbsStandard.UNDEFINED;
+
+    FrontendDvbtStandard tStd;
+
+    FrontendAnalogSifStandard sifStd;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanMessageType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanMessageType.aidl
new file mode 100644
index 0000000..f4d2ee0
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanMessageType.aidl
@@ -0,0 +1,95 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Scan Message Type for Frontend.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendScanMessageType {
+    /**
+     * Scan locked the signal.
+     */
+    LOCKED,
+
+    /**
+     * Scan stopped.
+     */
+    END,
+
+    /**
+     * Scan progress report.
+     */
+    PROGRESS_PERCENT,
+
+    /**
+     * Locked frequency report.
+     */
+    FREQUENCY,
+
+    /**
+     * Locked symbol rate.
+     */
+    SYMBOL_RATE,
+
+    /**
+     * Locked HIERARCHY for DVBT2 frontend.
+     */
+    HIERARCHY,
+
+    ANALOG_TYPE,
+
+    /**
+     * Locked Plp Ids for DVBT2 frontend.
+     */
+
+    PLP_IDS,
+
+    /**
+     * Locked group Ids for DVBT2 frontend.
+     */
+    GROUP_IDS,
+
+    /**
+     * Stream Ids.
+     */
+    INPUT_STREAM_IDS,
+
+    /**
+     * Locked signal standard.
+     */
+    STANDARD,
+
+    /**
+     * PLP status in a tuned frequency band for ATSC3 frontend.
+     */
+    ATSC3_PLP_INFO,
+
+    MODULATION,
+
+    DVBC_ANNEX,
+
+    HIGH_PRIORITY,
+
+    /**
+     * DVB-T CELL ID.
+     */
+    DVBT_CELL_IDS,
+
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanType.aidl
new file mode 100644
index 0000000..a548a3d
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendScanType.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Scan type for Frontend.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendScanType {
+    SCAN_UNDEFINED = 0,
+
+    SCAN_AUTO = 1 << 0,
+
+    SCAN_BLIND = 1 << 1,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendSettings.aidl
new file mode 100644
index 0000000..f78b2ae
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendSettings.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendAnalogSettings;
+import android.hardware.tv.tuner.FrontendAtsc3Settings;
+import android.hardware.tv.tuner.FrontendAtscSettings;
+import android.hardware.tv.tuner.FrontendDvbcSettings;
+import android.hardware.tv.tuner.FrontendDvbsSettings;
+import android.hardware.tv.tuner.FrontendDvbtSettings;
+import android.hardware.tv.tuner.FrontendIsdbs3Settings;
+import android.hardware.tv.tuner.FrontendIsdbsSettings;
+import android.hardware.tv.tuner.FrontendIsdbtSettings;
+import android.hardware.tv.tuner.FrontendDtmbSettings;
+
+/**
+ * Signal Settings for Frontend.
+ * @hide
+ */
+@VintfStability
+union FrontendSettings {
+    FrontendAnalogSettings analog;
+
+    FrontendAtscSettings atsc;
+
+    FrontendAtsc3Settings atsc3;
+
+    FrontendDvbsSettings dvbs;
+
+    FrontendDvbcSettings dvbc;
+
+    FrontendDvbtSettings dvbt;
+
+    FrontendIsdbsSettings isdbs;
+
+    FrontendIsdbs3Settings isdbs3;
+
+    FrontendIsdbtSettings isdbt;
+
+    FrontendDtmbSettings dtmb;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendSpectralInversion.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendSpectralInversion.aidl
new file mode 100644
index 0000000..232385b
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendSpectralInversion.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Spectral Inversion Type.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendSpectralInversion {
+    UNDEFINED,
+
+    NORMAL,
+
+    INVERTED,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl
new file mode 100644
index 0000000..ae6e46f
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl
@@ -0,0 +1,245 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendBandwidth;
+import android.hardware.tv.tuner.FrontendDvbtHierarchy;
+import android.hardware.tv.tuner.FrontendGuardInterval;
+import android.hardware.tv.tuner.FrontendInnerFec;
+import android.hardware.tv.tuner.FrontendInterleaveMode;
+import android.hardware.tv.tuner.FrontendIsdbtMode;
+import android.hardware.tv.tuner.FrontendIsdbtPartialReceptionFlag;
+import android.hardware.tv.tuner.FrontendModulation;
+import android.hardware.tv.tuner.FrontendModulationStatus;
+import android.hardware.tv.tuner.FrontendRollOff;
+import android.hardware.tv.tuner.FrontendSpectralInversion;
+import android.hardware.tv.tuner.FrontendStatusAtsc3PlpInfo;
+import android.hardware.tv.tuner.FrontendTransmissionMode;
+import android.hardware.tv.tuner.LnbVoltage;
+
+/**
+ * The status for Frontend.
+ * @hide
+ */
+@VintfStability
+union FrontendStatus {
+    /**
+     * Lock status for Demod in True/False.
+     */
+    boolean isDemodLocked;
+
+    /**
+     * SNR value measured by 0.001 dB.
+     */
+    int snr;
+
+    /**
+     * The number of error bit per 1 billion bits.
+     */
+    int ber;
+
+    /**
+     * The number of error package per 1 billion packages.
+     */
+    int per;
+
+    /**
+     * The number of error bit per 1 billion bits before FEC.
+     */
+    int preBer;
+
+    /**
+     * Signal Quality in percent.
+     */
+    int signalQuality;
+
+    /**
+     * Signal Strength measured by 0.001 dBm.
+     */
+    int signalStrength;
+
+    /**
+     * Symbols per second
+     */
+    int symbolRate;
+
+    FrontendInnerFec innerFec;
+
+    FrontendModulationStatus modulationStatus;
+
+    FrontendSpectralInversion inversion;
+
+    LnbVoltage lnbVoltage;
+
+    int plpId;
+
+    boolean isEWBS;
+
+    /**
+     * AGC value is normalized from 0 to 255.
+     * Larger AGC values indicate it is applying more gain.
+     */
+    int agc;
+
+    boolean isLnaOn;
+
+    /**
+     * Layer Error status.
+     *
+     * The order of the vectors is in ascending order of the required CNR (Contrast-to-noise ratio).
+     * The most robust layer is the first. For example, in ISDB-T, isLayerError[0] is the
+     * information of layer A. isLayerError[1] is the information of layer B.
+     */
+    boolean[] isLayerError;
+
+    /**
+     * MER value measured by 0.001 dB
+     */
+    int mer;
+
+    /**
+     * Frequency difference in Hertz.
+     */
+    long freqOffset;
+
+    FrontendDvbtHierarchy hierarchy;
+
+    boolean isRfLocked;
+
+    /**
+     * A list of PLP status for tuned PLPs for ATSC3 frontend.
+     */
+    FrontendStatusAtsc3PlpInfo[] plpInfo;
+
+    /**
+     * Modulation status.
+     *
+     * The order of the vectors is in ascending order of the required CNR (Contrast-to-noise ratio).
+     * The most robust layer is the first. For example, in ISDB-T, modulations[0] is the information
+     * of layer A. modulations[1] is the information of layer B.
+     */
+    FrontendModulation[] modulations;
+
+    /**
+     * Bit error ratio status.
+     *
+     * The order of the vectors is in ascending order of the required CNR (Contrast-to-noise ratio).
+     * The most robust layer is the first. For example, in ISDB-T, bers[0] is the information of
+     * layer A. bers[1] is the information of layer B.
+     */
+    int[] bers;
+
+    /**
+     * Code rate status.
+     *
+     * The order of the vectors is in ascending order of the required CN. The most robust layer is
+     * the first. For example, in ISDB-T, codeRates[0] is the information of layer A. codeRates[1]
+     * is the information of layer B.
+     */
+    FrontendInnerFec[] codeRates;
+
+    /**
+     * Bandwidth status.
+     */
+    FrontendBandwidth bandwidth;
+
+    /**
+     * Guard interval status.
+     */
+    FrontendGuardInterval interval;
+
+    /**
+     * Transmission mode status.
+     */
+    FrontendTransmissionMode transmissionMode;
+
+    /**
+     * Uncorrectable Error Counts of the frontend's Physical Layer Pipe (PLP)
+     * since the last tune operation.
+     */
+    int uec;
+
+    /**
+     * The current DVB-T2 system id status.
+     */
+    int systemId;
+
+    /**
+     * Frontend Interleaving Modes.
+     *
+     * The order of the vectors is in ascending order of the required CNR (Contrast-to-noise ratio).
+     * The most robust layer is the first. For example, in ISDB-T, interleaving[0] is the
+     * information of layer A. interleaving[1] is the information of layer B.
+     */
+    FrontendInterleaveMode[] interleaving;
+
+    /**
+     * Segments in ISDB-T Specification of all the channels.
+     *
+     * The order of the vectors is in ascending order of the required CNR (Contrast-to-noise ratio).
+     * The most robust layer is the first. For example, in ISDB-T, isdbtSegment[0] is the
+     * information of layer A. isdbtSegment[1] is the information of layer B.
+     */
+    int[] isdbtSegment;
+
+    /**
+     * Transport Stream Data Rate in BPS of the current channel.
+     */
+    int[] tsDataRate;
+
+    /**
+     * Roll Off Type status of the frontend.
+     */
+    FrontendRollOff rollOff;
+
+    /**
+     * If the frontend currently supports MISO or not.
+     */
+    boolean isMiso;
+
+    /**
+     * If the frontend code rate is linear or not.
+     */
+    boolean isLinear;
+
+    /**
+     * If short frames is enabled or not.
+     */
+    boolean isShortFrames;
+
+    /**
+     * ISDB-T Mode.
+     */
+    FrontendIsdbtMode isdbtMode;
+
+    /**
+     * ISDB-T Partial Reception Flag.
+     */
+    FrontendIsdbtPartialReceptionFlag partialReceptionFlag;
+
+    /**
+     * Stream ID list included in a transponder.
+     */
+    int[] streamIdList;
+
+    /**
+     * DVB-T Cell Id.
+     */
+    int[] dvbtCellIds;
+
+
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusAtsc3PlpInfo.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusAtsc3PlpInfo.aidl
new file mode 100644
index 0000000..6b44bc0
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusAtsc3PlpInfo.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Status for each tuning PLPs
+ * @hide
+ */
+@VintfStability
+parcelable FrontendStatusAtsc3PlpInfo {
+    /**
+     * PLP Id value.
+     */
+    int plpId;
+
+    /**
+     * Demod Lock/Unlock status of this particular PLP.
+     */
+    boolean isLocked;
+
+    /**
+     * Uncorrectable Error Counts (UEC) of this particular PLP since last tune operation.
+     */
+    int uec;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl
new file mode 100644
index 0000000..e7da517
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl
@@ -0,0 +1,231 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Frontend Status Type.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendStatusType {
+    /**
+     * Lock status for Demod.
+     */
+    DEMOD_LOCK,
+
+    /**
+     * Signal to Noise Ratio.
+     */
+    SNR,
+
+    /**
+     * Bit Error Ratio.
+     */
+    BER,
+
+    /**
+     * Packages Error Ratio.
+     */
+    PER,
+
+    /**
+     * Bit Error Ratio before FEC.
+     */
+    PRE_BER,
+
+    /**
+     * Signal Quality (0..100). Good data over total data in percent can be
+     * used as a way to present Signal Quality.
+     */
+    SIGNAL_QUALITY,
+
+    /**
+     * Signal Strength.
+     */
+    SIGNAL_STRENGTH,
+
+    /**
+     * Symbol Rate.
+     */
+    SYMBOL_RATE,
+
+    /**
+     * Forward Error Correction Type.
+     */
+    FEC,
+
+    /**
+     * Modulation Type.
+     */
+    MODULATION,
+
+    /**
+     * Spectral Inversion Type.
+     */
+    SPECTRAL,
+
+    /**
+     * LNB Voltage.
+     */
+    LNB_VOLTAGE,
+
+    /**
+     * Physical Layer Pipe ID.
+     */
+    PLP_ID,
+
+    /**
+     * Status for Emergency Warning Broadcasting System.
+     */
+    EWBS,
+
+    /**
+     * Automatic Gain Control.
+     */
+    AGC,
+
+    /**
+     * Low Noise Amplifier.
+     */
+    LNA,
+
+    /**
+     * Error status by layer.
+     */
+    LAYER_ERROR,
+
+    /**
+     * Moduration Error Ratio.
+     */
+    MER,
+
+    /**
+     * Difference between tuning frequency and actual locked frequency.
+     */
+    FREQ_OFFSET,
+
+    /**
+     * Hierarchy for DVBT.
+     */
+    HIERARCHY,
+
+    /**
+     * Lock status for RF.
+     */
+    RF_LOCK,
+
+    /**
+     * PLP information in a frequency band for ATSC3.0 frontend.
+     */
+    ATSC3_PLP_INFO,
+
+    /**
+     * Modulation Types.
+     */
+    MODULATIONS,
+
+    /**
+     * Bit Error Ratios.
+     */
+    BERS,
+    /**
+     * Code Rates.
+     */
+    CODERATES,
+
+    /**
+     * Extended Bandwidth.
+     */
+    BANDWIDTH,
+
+    /**
+     * Extended Guard Intervals.
+     */
+    GUARD_INTERVAL,
+
+    /**
+     * Extended Transmission Mode.
+     */
+    TRANSMISSION_MODE,
+
+    /**
+     * Uncorrectable Error Counts of the frontend's Physical Layer Pipe (PLP)
+     * since the last tune operation.
+     */
+    UEC,
+
+    /**
+     * DVB-T2 System Id.
+     */
+    T2_SYSTEM_ID,
+
+    /**
+     * Frontend Interleaving Modes.
+     */
+    INTERLEAVINGS,
+
+    /**
+     * Segments in ISDB-T Specification of all the channels.
+     */
+    ISDBT_SEGMENTS,
+
+    /**
+     * Transport Stream Data Rate in BPS of the current channel.
+     */
+    TS_DATA_RATES,
+
+    /**
+     * Roll Off Type status of the frontend.
+     */
+    ROLL_OFF,
+
+    /**
+     * If the frontend currently supports MISO or not.
+     */
+    IS_MISO,
+
+    /**
+     * If the frontend code rate is linear or not.
+     */
+    IS_LINEAR,
+
+    /**
+     * If short frames is enabled or not.
+     */
+    IS_SHORT_FRAMES,
+
+    /**
+     * ISDB-T Mode.
+     */
+    ISDBT_MODE,
+
+    /**
+     * ISDB-T Partial Reception Flag.
+     */
+    ISDBT_PARTIAL_RECEPTION_FLAG,
+
+    /**
+     * Stream ID list included in a transponder.
+     */
+   STREAM_ID_LIST,
+
+   /**
+    * DVB-T Cell Id.
+    */
+   DVBT_CELL_IDS,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendTransmissionMode.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendTransmissionMode.aidl
new file mode 100644
index 0000000..42b8718
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendTransmissionMode.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendIsdbtMode;
+import android.hardware.tv.tuner.FrontendDtmbTransmissionMode;
+import android.hardware.tv.tuner.FrontendDvbtTransmissionMode;
+
+/**
+ * @hide
+ */
+@VintfStability
+union FrontendTransmissionMode {
+    FrontendDvbtTransmissionMode dvbt = FrontendDvbtTransmissionMode.UNDEFINED;
+
+    FrontendIsdbtMode isdbt;
+
+    FrontendDtmbTransmissionMode dtmb;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendType.aidl
new file mode 100644
index 0000000..8ade389
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendType.aidl
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Extended Frontend Type.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum FrontendType {
+    UNDEFINED = 0,
+
+    ANALOG,
+
+    /**
+     * Advanced Television Systems Committee (ATSC) Standard A/72.
+     */
+    ATSC,
+
+    /**
+     * Advanced Television Systems Committee (ATSC 3.0) Standard A/300.
+     */
+    ATSC3,
+
+    /**
+     * Digital Video Broadcasting - Cable
+     * DVB Cable Frontend Standard ETSI EN 300 468 V1.15.1.
+     */
+    DVBC,
+
+    /**
+     * Digital Video Broadcasting - Satellite
+     * DVB Satellite Frontend Standard ETSI EN 300 468 V1.15.1 and
+     * ETSI EN 302 307-2 V1.1.1.
+     */
+    DVBS,
+
+    /**
+     * Digital Video Broadcasting - Terrestrial
+     * DVB Terrestrial Frontend Standard ETSI EN 300 468 V1.15.1 and
+     * ETSI EN 302 755 V1.4.1.
+     */
+    DVBT,
+
+    /**
+     * Integrated Services Digital Broadcasting-Satellite (ISDB-S)
+     * ARIB STD-B20 is technical document of ISDB-S.
+     */
+    ISDBS,
+
+    /**
+     * Integrated Services Digital Broadcasting-Satellite (ISDB-S)
+     * ARIB STD-B44 is technical document of ISDB-S3.
+     */
+    ISDBS3,
+
+    /**
+     * Integrated Services Digital Broadcasting-Terrestrial (ISDB-T or SBTVD)
+     * ABNT NBR 15603 is technical document of ISDB-T.
+     */
+    ISDBT,
+
+    /**
+     * DTMB (Digital Terrestrial Multimedia Broadcast) standard.
+     */
+    DTMB,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IDemux.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IDemux.aidl
new file mode 100644
index 0000000..7d69240
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IDemux.aidl
@@ -0,0 +1,133 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterType;
+import android.hardware.tv.tuner.DvrType;
+import android.hardware.tv.tuner.IDvr;
+import android.hardware.tv.tuner.IDvrCallback;
+import android.hardware.tv.tuner.IFilter;
+import android.hardware.tv.tuner.IFilterCallback;
+import android.hardware.tv.tuner.ITimeFilter;
+
+/**
+ * Demultiplexer(Demux) takes a single multiplexed input and splits it into
+ * one or more output.
+ * @hide
+ */
+@VintfStability
+interface IDemux {
+    /**
+     * Set a frontend resource as data input of the demux
+     *
+     * It is used by the client to specify a hardware frontend as data source of
+     * this demux instance. A demux instance can have only one data source.
+     */
+    void setFrontendDataSource(in int frontendId);
+
+    /**
+     * Open a new filter in the demux
+     *
+     * It is used by the client to open a filter in the demux.
+     *
+     * @param type the type of the filter to be added.
+     * @param bufferSize the buffer size of the filter to be opened. It's used
+     * to create a FMQ(Fast Message Queue) to hold data output from the filter.
+     * @param cb the callback for the filter to be used to send notifications
+     * back to the client.
+     *
+     * @return the filter instance of the newly added.
+     */
+    IFilter openFilter(in DemuxFilterType type, in int bufferSize,
+        in IFilterCallback cb);
+
+    /**
+     * Open time filter of the demux
+     *
+     * It is used by the client to open time filter of the demux.
+     *
+     * @return the time filter instance of the newly added.
+     */
+    ITimeFilter openTimeFilter();
+
+    /**
+     * Get hardware sync ID for audio and video.
+     *
+     * It is used by the client to get the hardware sync ID for audio and video.
+     *
+     * @param filter the filter instance.
+     *
+     * @return the ID of hardware A/V sync.
+     */
+    int getAvSyncHwId(in IFilter filter);
+
+    /**
+     * Get current time stamp to use for A/V sync
+     *
+     * It is used by the client to get current time stamp for A/V sync. HW is
+     * supported to increment and maintain current time stamp.
+     *
+     * @param avSyncHwId the hardware id of A/V sync.
+     *
+     * @return the current time stamp of hardware A/V sync. The time stamp
+     * based on 90KHz has the same format as PTS (Presentation Time Stamp).
+     */
+    long getAvSyncTime(in int avSyncHwId);
+
+    /**
+     * Close the Demux instance
+     *
+     * It is used by the client to release the demux instance. HAL clear
+     * underneath resource. client mustn't access the instance any more.
+     */
+    void close();
+
+    /**
+     * Open a DVR (Digital Video Record) instance in the demux
+     *
+     * It is used by the client to record and playback.
+     *
+     * @param type specify which kind of DVR to open.
+     * @param bufferSize the buffer size of the output to be added. It's used to
+     * create a FMQ(Fast Message Queue) to hold data from selected filters.
+     * @param cb the callback for the DVR to be used to send notifications
+     * back to the client.
+     *
+     * @return the newly opened DVR instance.
+     */
+    IDvr openDvr(in DvrType type, in int bufferSize, in IDvrCallback cb);
+
+    /**
+     * Connect Conditional Access Modules (CAM) through Common Interface (CI)
+     *
+     * It is used by the client to connect CI-CAM. The demux uses the output
+     * from the frontend as the input by default, and must change to use the
+     * output from CI-CAM as the input after this call take place.
+     *
+     * @param ciCamId specify CI-CAM Id to connect.
+     */
+    void connectCiCam(in int ciCamId);
+
+    /**
+     * Disconnect Conditional Access Modules (CAM)
+     *
+     * It is used by the client to disconnect CI-CAM. The demux will use the
+     * output from the frontend as the input after this call take place.
+     *
+     */
+    void disconnectCiCam();
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IDescrambler.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IDescrambler.aidl
new file mode 100644
index 0000000..8643828
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IDescrambler.aidl
@@ -0,0 +1,81 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxPid;
+import android.hardware.tv.tuner.IFilter;
+
+/**
+ * Descrambler is used to descramble input data.
+ * @hide
+ */
+@VintfStability
+interface IDescrambler {
+    /**
+     * Set a demux as source of the descrambler
+     *
+     * It is used by the client to specify a demux as source of this
+     * descrambler. A descrambler instance can have only one source, and
+     * this method can be only called once.
+     *
+     * @param demuxId the id of the demux to be used as descrambler's source.
+     */
+    void setDemuxSource(in int demuxId);
+
+    /**
+     * Set a key token to link descrambler to a key slot
+     *
+     * It is used by the client to link a hardware key slot to a descrambler.
+     * A descrambler instance can have only one key slot to link, but a key
+     * slot can hold a few keys for different purposes.
+     *
+     * @param keyToken the token to be used to link the key slot.
+     */
+    void setKeyToken(in byte[] keyToken);
+
+    /**
+     * Add packets' PID to the descrambler for descrambling
+     *
+     * It is used by the client to specify Package ID (PID) of packets which the
+     * descrambler start to descramble. Multiple PIDs can be added into one
+     * descrambler instance because descambling can happen simultaneously on
+     * packets from different PIDs.
+     *
+     * @param pid the PID of packets to start to be descrambled.
+     * @param filter an optional filter instance to identify upper stream.
+     */
+    void addPid(in DemuxPid pid, in IFilter optionalSourceFilter);
+
+    /**
+     * Remove packets' PID from the descrambler
+     *
+     * It is used by the client to specify Package ID (PID) of packets which the
+     * descrambler stop to descramble.
+     *
+     * @param pid the PID of packets to stop to be descrambled.
+     * @param filter an optional filter instance to identify upper stream.
+     */
+    void removePid(in DemuxPid pid, in IFilter optionalSourceFilter);
+
+    /**
+     * Release the descrambler instance
+     *
+     * It is used by the client to release the descrambler instance. HAL clear
+     * underneath resource. client mustn't access the instance any more.
+     */
+    void close();
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IDvr.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IDvr.aidl
new file mode 100644
index 0000000..0534f9d
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IDvr.aidl
@@ -0,0 +1,104 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+
+import android.hardware.tv.tuner.DvrSettings;
+import android.hardware.tv.tuner.IFilter;
+
+/**
+ * Digtal Video Record (DVR) interface provides record control on Demux's
+ * output buffer and playback control on Demux's input buffer.
+ * @hide
+ */
+@VintfStability
+interface IDvr {
+    /**
+     * Get the descriptor of the DVR's FMQ
+     *
+     * It is used by the client to get the descriptor of the DVR's Fast
+     * Message Queue. The FMQ is used to transfer record or playback data
+     * between the client and the HAL.
+     *
+     * @return the descriptor of the DVR's FMQ
+     */
+    void getQueueDesc(out MQDescriptor<byte, SynchronizedReadWrite> queue);
+
+    /**
+     * Configure the DVR.
+     *
+     * It is used by the client to configure the DVR interface.
+     *
+     * @param settings the settings of the DVR interface.
+     */
+    void configure(in DvrSettings settings);
+
+    /**
+     * Attach one filter to DVR interface for recording.
+     *
+     * It is used by the client to add the data filtered out from the filter
+     * to record.
+     *
+     * @param filter the instance of the attached filter.
+     */
+    void attachFilter(in IFilter filter);
+
+    /**
+     * Detach one filter from the DVR's recording.
+     *
+     * It is used by the client to remove the data of the filter from DVR's
+     * recording.
+     *
+     * @param filter the instance of the detached filter.
+     */
+    void detachFilter(in IFilter filter);
+
+    /**
+     * Start DVR.
+     *
+     * It is used by the client to ask the DVR to start consuming playback data
+     * or producing data for record.
+     */
+    void start();
+
+    /**
+     * Stop DVR.
+     *
+     * It is used by the client to ask the DVR to stop consuming playback data
+     * or producing data for record.
+     */
+    void stop();
+
+    /**
+     * Flush DVR data.
+     *
+     * It is used by the client to ask the DVR to flush the data which is
+     * not consumed by HAL for playback or the client for record yet.
+     */
+    void flush();
+
+    /**
+     * close the DVR instance to release resource for DVR.
+     *
+     * It is used by the client to close the DVR instance, and HAL clears
+     * underneath resource for this DVR instance. Client mustn't access the
+     * instance any more and all methods should return a failure.
+     */
+    void close();
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IDvrCallback.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IDvrCallback.aidl
new file mode 100644
index 0000000..46d4856
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IDvrCallback.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.PlaybackStatus;
+import android.hardware.tv.tuner.RecordStatus;
+
+/**
+ * This interface is used by the HAL to notify the DVR playback and record status
+ * back to the client, the cient implements the interfaces and passes a handle to
+ * the HAL.
+ * @hide
+ */
+@VintfStability
+oneway interface IDvrCallback {
+    /**
+     * Notify the client a new status of the demux's playback.
+     *
+     * @param status a new status of the demux's playback.
+     */
+    void onPlaybackStatus(in PlaybackStatus status);
+
+    /**
+     * Notify the client a new status of the demux's record.
+     *
+     * @param status a new status of the demux's record.
+     */
+    void onRecordStatus(in RecordStatus status);
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IFilter.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IFilter.aidl
new file mode 100644
index 0000000..28927d1
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IFilter.aidl
@@ -0,0 +1,199 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.common.NativeHandle;
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+import android.hardware.tv.tuner.AvStreamType;
+import android.hardware.tv.tuner.DemuxFilterMonitorEventType;
+import android.hardware.tv.tuner.DemuxFilterSettings;
+import android.hardware.tv.tuner.FilterDelayHint;
+import android.hardware.tv.tuner.IFilter;
+
+/**
+ * The Filter is used to filter wanted data according to the filter's
+ * configuration.
+ *
+ * Note that reconfiguring Filter must happen after the Filter is stopped.
+ * @hide
+ */
+@VintfStability
+interface IFilter {
+    /**
+     * Get the descriptor of the filter's FMQ
+     *
+     * It is used by the client to get the descriptor of the filter's Fast
+     * Message Queue. The data in FMQ is filtered out from demux input or upper
+     * stream's filter. The data is origanized to data blocks which may have
+     * different length. The length's information of one or multiple data blocks
+     * is sent to client through DemuxFilterEvent. The data in each block
+     * follows the stardard specified by filter's type.
+     * E.X. one data block from the filter with Main_Type==TS and Sub_Type==PES
+     * is Packetized Elementary Stream from Transport Stream according to
+     * ISO/IEC 13818-1.
+     *
+     * @return the descriptor of the filter's FMQ
+     */
+    void getQueueDesc(out MQDescriptor<byte, SynchronizedReadWrite> queue);
+
+    /**
+     * Release the Filter instance
+     *
+     * It is used by the client to release the Filter instance. HAL clear
+     * underneath resource. client mustn't access the instance any more.
+     */
+    void close();
+
+    /**
+     * Configure the filter.
+     *
+     * It is used by the client to configure the filter so that it can filter out
+     * intended data.
+     *
+     * @param settings the settings of the filter.
+     */
+    void configure(in DemuxFilterSettings settings);
+
+    /**
+     * Configure A/V filter’s stream type. This API only applies to A/V filters.
+     *
+     * @param avStreamType the stream type for A/V.
+     */
+    void configureAvStreamType(in AvStreamType avStreamType);
+
+    /**
+     * Configure additional Context ID on the IP filter.
+     *
+     * @param ipCid Context Id of the IP filter.
+     */
+    void configureIpCid(in int ipCid);
+
+    /**
+     * Configure the monitor event.
+     *
+     * The event for Scrambling Status should be sent at the following two scenarios:
+     *   1. When this method is called, the first detected scrambling status should be sent.
+     *   2. When the Scrambling status transits into different status, event should be sent.
+     *
+     * The event for IP CID change should be sent at the following two scenarios:
+     *   1. When this method is called, the first detected CID for the IP should be sent.
+     *   2. When the CID is changed to different value for the IP filter, event should be sent.
+     *
+     * @param monitorEventypes the DemuxFilterMonitorEventType events to monitor. Set
+     *        corresponding bit of the event to monitor. Reset to stop monitoring.
+     */
+    void configureMonitorEvent(in int monitorEventTypes);
+
+    /**
+     * Start the filter.
+     *
+     * It is used by the client to ask the filter to start filterring data.
+     */
+    void start();
+
+    /**
+     * Stop the filter.
+     *
+     * It is used by the client to ask the filter to stop filterring data.
+     * It won't discard the data already filtered out by the filter. The filter
+     * will be stopped and removed automatically if the demux is closed.
+     */
+    void stop();
+
+    /**
+     * Flush the filter.
+     *
+     * It is used by the client to ask the filter to flush the data which is
+     * already produced but not consumed yet.
+     */
+    void flush();
+
+    /**
+     * Get the shared AV memory handle. Use IFilter.releaseAvHandle to release
+     * the handle.
+     *
+     * When media filters are opened, call this API to initialize the share
+     * memory handle if it's needed.
+     *
+     * If DemuxFilterMediaEvent.avMemory contains file descriptor, share memory
+     * should be ignored.
+     *
+     * @param out avMemory A handle associated to the shared memory for audio or
+     *         video. avMemory.data[0] is normally an fd for ION memory. When
+     *         the avMemory->numFd is 0, the share memory is not initialized and
+     *         does not contain valid fd. avMemory.data[avMemory.numFds] is an
+     *         index used as a parameter of C2DataIdInfo to build C2 buffer in
+     *         Codec. No C2 buffer would be created if the index does not exist.
+     *
+     * @return the size of the shared av memory. It should be ignored when the share
+     *         memory is not initialized.
+     */
+    long getAvSharedHandle(out NativeHandle avMemory);
+
+    /**
+     * Get the 32-bit filter Id.
+     *
+     * It is used by the client to ask the hardware resource id for the filter.
+     *
+     * @return the hardware 32-bit resource Id for the filter.
+     */
+    int getId();
+
+    /**
+     * Get the 64-bit filter Id.
+     *
+     * It is used by the client to ask the hardware resource id for the filter.
+     *
+     * @return the hardware 64-bit resource Id for the filter.
+     */
+    long getId64Bit();
+
+    /**
+     * Release the handle reported by the HAL for AV memory.
+     *
+     * It is used by the client to notify the HAL that the AV handle won't be
+     * used any more in client side, so that the HAL can mark the memory
+     * presented by file descripor in the handle as released.
+     *
+     * @param avMemory A handle associated to the memory for audio or video.
+     * @param avDataId An Id provides additional information for AV data.
+     */
+    void releaseAvHandle(in NativeHandle avMemory, in long avDataId);
+
+    /**
+     * Set the filter's data source.
+     *
+     * A filter uses demux as data source by default. If the data was packetized
+     * by multiple protocols, multiple filters may need to work together to
+     * extract all protocols' header. Then a filter's data source can be output
+     * from another filter.
+     *
+     * @param filter the filter instance which provides data input. Switch to
+     * use demux as data source if the filter instance is NULL.
+     */
+    void setDataSource(in IFilter filter);
+
+    /**
+     * Set a delay hint.
+     *
+     * A delay hint should be used by the filter to rate limit calls to on
+     * FilterCallback.onFilterEvent by aggregating data according to the hint's
+     * specification.
+     */
+    void setDelayHint(in FilterDelayHint hint);
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IFilterCallback.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IFilterCallback.aidl
new file mode 100644
index 0000000..f4e01ee
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IFilterCallback.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxFilterEvent;
+import android.hardware.tv.tuner.DemuxFilterStatus;
+
+/**
+ * This interface is used by the HAL to notify the filter event and scan status
+ * back to the client, the cient implements the interfaces and passes a handle
+ * to the HAL.
+ * @hide
+ */
+@VintfStability
+oneway interface IFilterCallback {
+    /**
+     * Notify the client that a new filter event happened.
+     *
+     * @param events an array of DemuxFilterEvent.
+     */
+    void onFilterEvent(in DemuxFilterEvent[] events);
+
+    /**
+     * Notify the client a new status of a filter.
+     *
+     * @param status a new status of the filter.
+     */
+    void onFilterStatus(in DemuxFilterStatus status);
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IFrontend.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IFrontend.aidl
new file mode 100644
index 0000000..5b3ce39
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IFrontend.aidl
@@ -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.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendScanType;
+import android.hardware.tv.tuner.FrontendSettings;
+import android.hardware.tv.tuner.FrontendStatus;
+import android.hardware.tv.tuner.FrontendStatusType;
+import android.hardware.tv.tuner.IFrontendCallback;
+
+/**
+ * A Tuner Frontend is used to tune to a frequency and lock signal.
+ *
+ * IFrontend provides a bit stream to the Tuner Demux interface.
+ * @hide
+ */
+@VintfStability
+interface IFrontend {
+    /**
+     * Set the frontend callback.
+     *
+     * IFrontendCallback is used by the client to receive events from the Frontend.
+     * Only one callback per IFrontend instance is supported. The callback
+     * will be replaced if it's set again.
+     *
+     * @param callback Callback object to pass Frontend events to the system.
+     *        The previously registered callback must be replaced with this one.
+     *        It can be null.
+     */
+    void setCallback(in IFrontendCallback callback);
+
+    /**
+     * Tunes the frontend to using the settings given.
+     *
+     * This locks the frontend to a frequency by providing signal
+     * delivery information. If previous tuning isn't completed, this call MUST
+     * stop previous tuning, and start a new tuning.
+     * Tune is an async call, with LOCKED or NO_SIGNAL events sent via callback.
+     *
+     * @param settings Signal delivery information the frontend uses to
+     * search and lock the signal.
+     */
+    void tune(in FrontendSettings settings);
+
+    /**
+     * Stops a previous tuning.
+     *
+     * If the method completes successfully the frontend is no longer tuned and no data
+     * will be sent to attached demuxes.
+     */
+    void stopTune();
+
+    /**
+     * Releases the Frontend instance
+     *
+     * Associated resources are released.  close may be called more than once.
+     * Calls to any other method after this will return an error
+     */
+    void close();
+
+    /**
+     * Scan the frontend to use the settings given.
+     *
+     * This uses the frontend to start a scan from signal delivery information.
+     * If previous scan isn't completed, this call MUST stop previous scan,
+     * and start a new scan.
+     * Scan is an async call, with FrontendScanMessage sent via callback.
+     *
+     * @param settings Signal delivery information which the frontend uses to
+     * scan the signal.
+     * @param type the type which the frontend uses to scan the signal.
+     */
+    void scan(in FrontendSettings settings, in FrontendScanType type);
+
+    /**
+     * Stops a previous scanning.
+     *
+     * If the method completes successfully, the frontend stop previous
+     * scanning.
+     */
+    void stopScan();
+
+    /**
+     * Gets the statuses of the frontend.
+     *
+     * This retrieve the statuses of the frontend for given status types.
+     *
+     * @param statusTypes an array of status type which the caller request.
+     *
+     * @return an array of statuses which response the caller's request.
+     */
+    FrontendStatus[] getStatus(in FrontendStatusType[] statusTypes);
+
+    /**
+     * Sets Low-Noise Block downconverter (LNB) for satellite frontend.
+     *
+     * This assigns a hardware LNB resource to the satellite frontend. It can be
+     * called multiple times to update LNB assignment. The LNB resource must be
+     * released when the frontend is closed.
+     *
+     * @param lnbId the Id of assigned LNB resource.
+     */
+    void setLnb(in int lnbId);
+
+    /**
+     * Link Conditional Access Modules (CAM) to Frontend support Common
+     * Interface (CI) bypass mode.
+     *
+     * The client may use this to link CI-CAM to a frontend. CI bypass mode
+     * requires that the CICAM also receives the TS concurrently from the
+     * frontend when the Demux is receiving the TS directly from the frontend.
+     *
+     * @param ciCamId specify CI-CAM Id to link.
+     *
+     * @return the Local Transport Stream Id.
+     */
+    int linkCiCam(in int ciCamId);
+
+    /**
+     * Unlink Conditional Access Modules (CAM) to Frontend.
+     *
+     * @param ciCamId specify CI-CAM Id to unlink.
+     */
+    void unlinkCiCam(in int ciCamId);
+
+    /**
+     * Request Hardware information about the frontend.
+     *
+     * The client may use this to collect vendor specific hardware information, e.g. RF
+     * chip version, Demod chip version, detailed status of dvbs blind scan, etc.
+     *
+     * @return the frontend hardware information.
+     */
+    String getHardwareInfo();
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IFrontendCallback.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IFrontendCallback.aidl
new file mode 100644
index 0000000..6822869
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IFrontendCallback.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendEventType;
+import android.hardware.tv.tuner.FrontendScanMessage;
+import android.hardware.tv.tuner.FrontendScanMessageType;
+
+/**
+ * This interface is used by the HAL to notify the fronted event and scan messages
+ * back to the client, the cient implements the interfaces and passes a handle to
+ * the HAL.
+ * @hide
+ */
+@VintfStability
+oneway interface IFrontendCallback {
+    /**
+     * Notify the client that a new event happened on the frontend.
+     *
+     * @param frontendEventType the event type.
+     */
+    void onEvent(in FrontendEventType frontendEventType);
+
+    /**
+     * The callback function that must be called by HAL implementation to notify
+     * the client of scan messages.
+     *
+     * @param type the type of scan message.
+     * @param message the scan message sent by HAL to the client.
+     */
+    void onScanMessage(in FrontendScanMessageType type,
+        in FrontendScanMessage message);
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/ILnb.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/ILnb.aidl
new file mode 100644
index 0000000..28eae45
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/ILnb.aidl
@@ -0,0 +1,85 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.ILnbCallback;
+import android.hardware.tv.tuner.LnbPosition;
+import android.hardware.tv.tuner.LnbTone;
+import android.hardware.tv.tuner.LnbVoltage;
+
+/**
+ * A Tuner LNB (low-noise block downconverter) is used by satellite frontend
+ * to receive the microwave signal from the satellite, amplify it, and
+ * downconvert the frequency to a lower frequency.
+ * @hide
+ */
+@VintfStability
+interface ILnb {
+    /**
+     * Set the lnb callback.
+     *
+     * ILnbCallback is used by the client to receive events from the Lnb.
+     * Only one callback per ILnb instance is supported. The callback
+     * will be replaced if it's set again.
+     *
+     * @param callback Callback object to pass Lnb events to the system.
+     *        The previously registered callback must be replaced with this one.
+     *        It can be null.
+     */
+    void setCallback(in ILnbCallback callback);
+
+    /**
+     * Set the lnb's power voltage.
+     *
+     * @param voltage the power's voltage the Lnb to use.
+     */
+    void setVoltage(in LnbVoltage voltage);
+
+    /**
+     * Set the lnb's tone mode.
+     *
+     * @param tone the tone mode the Lnb to use.
+     */
+    void setTone(in LnbTone tone);
+
+    /**
+     * Select the lnb's position.
+     *
+     * @param position the position the Lnb to use.
+     */
+    void setSatellitePosition(in LnbPosition position);
+
+    /**
+     *  Sends DiSEqC (Digital Satellite Equipment Control) message.
+     *
+     * Client sends DiSeqc message to DiSEqc to LNB. The response message from
+     * the device comes back to the client through frontend's callback
+     * onDiseqcMessage.
+     *
+     * @param diseqcMessage a byte array of data for DiSEqC message which is
+     *        specified by EUTELSAT Bus Functional Specification Version 4.2.
+     */
+    void sendDiseqcMessage(in byte[] diseqcMessage);
+
+    /**
+     * Releases the LNB instance
+     *
+     * Associated resources are released.  close may be called more than once.
+     * Calls to any other method after this will return an error
+     */
+    void close();
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/ILnbCallback.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/ILnbCallback.aidl
new file mode 100644
index 0000000..98ef141
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/ILnbCallback.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+import android.hardware.tv.tuner.LnbEventType;
+
+/**
+ * This interface is used by the HAL to notify the Lnb event and DiSEqC (Digital
+ * Satellite Equipment Control) message back to the client, the cient implements
+ * the interfaces and passes a handle to the HAL.
+ * @hide
+ */
+@VintfStability
+oneway interface ILnbCallback {
+    /**
+     * The callback function that must be called by HAL implementation to notify
+     * the client of new DiSEqC message.
+     *
+     * @param diseqcMessage a byte array of data for DiSEqC (Digital Satellite
+     * Equipment Control) message which is specified by EUTELSAT Bus Functional
+     * Specification Version 4.2.
+     */
+    void onDiseqcMessage(in byte[] diseqcMessage);
+
+    /**
+     * Notify the client that a new event happened on the Lnb.
+     *
+     * @param LnbEventType the event type.
+     */
+    void onEvent(in LnbEventType lnbEventType);
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/ITimeFilter.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/ITimeFilter.aidl
new file mode 100644
index 0000000..dee6cd8
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/ITimeFilter.aidl
@@ -0,0 +1,71 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Timer Filter is used by Demux to filter data based on time stamp.
+ * @hide
+ */
+@VintfStability
+interface ITimeFilter {
+    /**
+     * Set time stamp for time based filter.
+     *
+     * It is used by the client to set initial time stamp and enable time
+     * filtering. The time will be incremented locally. The demux discards
+     * the content which time stamp is older than the time in the time filter.
+     *
+     * @param timeStamp initial time stamp for the time filter. It based on
+     * 90KHz has the same format as PTS (Presentation Time Stamp).
+     */
+    void setTimeStamp(in long timeStamp);
+
+    /**
+     * Clear the time stamp in the time filter.
+     *
+     * It is used by the client to clear the time value of the time filter,
+     * then disable time filter.
+     */
+    void clearTimeStamp();
+
+    /**
+     * Get the current time in the time filter.
+     *
+     * It is used by the client to inquiry current time in the time filter.
+     *
+     * @return the current time stamp in the time filter.
+     */
+    long getTimeStamp();
+
+    /**
+     * Get the time from the beginning of current data source.
+     *
+     * It is used by the client to inquiry the time stamp from the beginning
+     * of current data source.
+     *
+     * @return the time stamp from the beginning of current data source.
+     */
+    long getSourceTime();
+
+    /**
+     * Close the Time Filter instance
+     *
+     * It is used by the client to release the demux instance. HAL clear
+     * underneath resource. client mustn't access the instance any more.
+     */
+    void close();
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl
new file mode 100644
index 0000000..1fcbb06
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl
@@ -0,0 +1,130 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.DemuxCapabilities;
+import android.hardware.tv.tuner.FrontendInfo;
+import android.hardware.tv.tuner.IDemux;
+import android.hardware.tv.tuner.IDescrambler;
+import android.hardware.tv.tuner.IFrontend;
+import android.hardware.tv.tuner.ILnb;
+
+/**
+ * Top level interface to manage Frontend, Demux and Decrambler hardware
+ * resources which are needed for Android TV.
+ * @hide
+ */
+@VintfStability
+@SuppressWarnings(value={"out-array"})
+interface ITuner {
+    /**
+     * Get Frontend IDs
+     *
+     * It is used by the client to get all available frontends' IDs.
+     *
+     * @return an array of IDs for the available Frontends.
+     */
+    int[] getFrontendIds();
+
+    /**
+     * Create a new instance of Frontend given a frontendId.
+     *
+     * It is used by the client to create a frontend instance.
+     *
+     * @param frontendId the id of the frontend to be opened.
+     *
+     * @return the newly created frontend interface.
+     */
+    IFrontend openFrontendById(in int frontendId);
+
+    /**
+     * Create a new instance of Demux.
+     *
+     * It is used by the client to create a Demux instance.
+     *
+     * @param out demuxId the newly created demux id will be the first
+     *        element of the array.
+     *
+     * @return the newly created demux interface.
+     */
+    IDemux openDemux(out int[] demuxId);
+
+    /**
+     * Retrieve the Demux's Capabilities.
+     *
+     * @return the Demux's Capabilities.
+     */
+    DemuxCapabilities getDemuxCaps();
+
+    /**
+     * Create a new instance of Descrambler.
+     *
+     * It is used by the client to create a Descrambler instance.
+     *
+     * @return the newly created descrambler interface.
+     */
+    IDescrambler openDescrambler();
+
+    /**
+     * Retrieve the frontend's information.
+     *
+     * @return the frontend's information.
+     */
+    FrontendInfo getFrontendInfo(in int frontendId);
+
+    /**
+     * Get low-noise block downconverter (LNB) IDs.
+     *
+     * It is used by the client to get all available LNBs' IDs.
+     *
+     * @return an array of LnbId for the available LNBs.
+     */
+    int[] getLnbIds();
+
+    /**
+     * Create a new instance of Lnb given a lnbId.
+     *
+     * It is used by the client to create a Lnb instance for satellite Frontend.
+     *
+     * @param lnbId the id of the LNB to be opened.
+     *
+     * @return the newly created Lnb interface.
+     */
+    ILnb openLnbById(in int lnbId);
+
+    /**
+     * Create a new instance of Lnb given a LNB name.
+     *
+     * It is used by the client to create a LNB instance for external device.
+     *
+     * @param lnbName the name for an external LNB to be opened. The app
+     *        provides the name. Frammework doesn't depend on the name, instead
+     *        use lnbId return from this call.
+     * @param out demuxId the newly opened Lnb id will be the first element of
+     *        the array.
+     *
+     * @return the newly opened Lnb iterface.
+     */
+    ILnb openLnbByName(in String lnbName, out int[] lnbId);
+
+    /**
+     * Enable or Disable Low Noise Amplifier (LNA).
+     *
+     * @param bEnable true if activate LNA module; false if deactivate LNA
+     */
+    void setLna(in boolean bEnable);
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/LnbEventType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/LnbEventType.aidl
new file mode 100644
index 0000000..a6230b0
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/LnbEventType.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Lnb Event Type.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum LnbEventType {
+    DISEQC_RX_OVERFLOW,
+
+    /**
+     * If LNB detect that outgoing Diseqc message isn't delivered on time.
+     */
+    DISEQC_RX_TIMEOUT,
+
+    /**
+     * If LNB detect that the incoming Diseqc message has parity error.
+     */
+    DISEQC_RX_PARITY_ERROR,
+
+    /**
+     * If LNB detect that the LNB is overload.
+     */
+    LNB_OVERLOAD,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/LnbPosition.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/LnbPosition.aidl
new file mode 100644
index 0000000..067f6b1
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/LnbPosition.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * The Position of LNB.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum LnbPosition {
+    UNDEFINED,
+
+    POSITION_A,
+
+    POSITION_B,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/LnbTone.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/LnbTone.aidl
new file mode 100644
index 0000000..f1d1598
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/LnbTone.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Tone Type for LNB.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum LnbTone {
+    NONE,
+
+    CONTINUOUS,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/LnbVoltage.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/LnbVoltage.aidl
new file mode 100644
index 0000000..03a42f2
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/LnbVoltage.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Power Voltage Type for LNB.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum LnbVoltage {
+    NONE,
+
+    VOLTAGE_5V,
+
+    VOLTAGE_11V,
+
+    VOLTAGE_12V,
+
+    VOLTAGE_13V,
+
+    VOLTAGE_14V,
+
+    VOLTAGE_15V,
+
+    VOLTAGE_18V,
+
+    VOLTAGE_19V,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/PlaybackSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/PlaybackSettings.aidl
new file mode 100644
index 0000000..fc5cf63
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/PlaybackSettings.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.DataFormat;
+
+/**
+ * The Setting for the playback in DVR.
+ * @hide
+ */
+@VintfStability
+parcelable PlaybackSettings {
+    /**
+     * Register for interested PlaybackStatus events so that the HAL can send these
+     * PlaybackStatus events back to client.
+     */
+    int statusMask;
+
+    /**
+     * Unused space size in bytes in the playback. The HAL uses it to trigger
+     * InputStatus::SPACE_ALMOST_EMPTY.
+     */
+    long lowThreshold;
+
+    /**
+     * Unused space size in bytes in the playback. The HAL uses it to trigger
+     * InputStatus::SPACE_ALMOST_FULL.
+     */
+    long highThreshold;
+
+    /**
+     * The data format in the playback.
+     */
+    DataFormat dataFormat = DataFormat.UNDEFINED;
+
+    /**
+     * The packet size in bytes in the playback.
+     */
+    long packetSize;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/PlaybackStatus.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/PlaybackStatus.aidl
new file mode 100644
index 0000000..545dc89
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/PlaybackStatus.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * A status of the playback in DVR.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum PlaybackStatus {
+    /**
+     * The space of the demux's playback is empty.
+     */
+    SPACE_EMPTY = 1 << 0,
+
+    /**
+     * The spece of the demux's playback is almost empty.
+     */
+    SPACE_ALMOST_EMPTY = 1 << 1,
+
+    /**
+     * The space of the demux's playback is almost full.
+     */
+    SPACE_ALMOST_FULL = 1 << 2,
+
+    /**
+     * The space of the demux's playback is full.
+     */
+    SPACE_FULL = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/RecordSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/RecordSettings.aidl
new file mode 100644
index 0000000..ac851c6
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/RecordSettings.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.tv.tuner;
+
+import android.hardware.tv.tuner.DataFormat;
+
+/**
+ * The Settings for the record in DVR.
+ * @hide
+ */
+@VintfStability
+parcelable RecordSettings {
+    /**
+     * Register for interested RecordStatus events so that the HAL can send these
+     * PlaybackStatus events back to client.
+     */
+    int statusMask;
+
+    /**
+     * Unconsumed data size in bytes in the record. The HAL uses it to trigger
+     * OutputStatus::LOW_WATER.
+     */
+    long lowThreshold;
+
+    /**
+     * Unconsumed data size in bytes in the record. The HAL uses it to trigger
+     * OutputStatus::High_WATER.
+     */
+    long highThreshold;
+
+    /**
+     * The data format in the record.
+     */
+    DataFormat dataFormat = DataFormat.UNDEFINED;
+
+    /**
+     * The packet size in bytes in the record.
+     */
+    long packetSize;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/RecordStatus.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/RecordStatus.aidl
new file mode 100644
index 0000000..64d9bd4
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/RecordStatus.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * A status of data in the filter's buffer.
+ * @hide
+ */
+@VintfStability
+@Backing(type="byte")
+enum RecordStatus {
+    /**
+     * The data in the filter buffer is ready to be read.
+     */
+    DATA_READY = 1 << 0,
+
+    /**
+     * The available data amount in the filter buffer is at low level which is
+     * set to 25 percent by default.
+     */
+    LOW_WATER = 1 << 1,
+
+    /**
+     * The available data amount in the filter buffer is at high level which is
+     * set to 75 percent by default.
+     */
+    HIGH_WATER = 1 << 2,
+
+    /**
+     * The data in the filter buffer is full and newly filtered data is being
+     * discarded.
+     */
+    OVERFLOW = 1 << 3,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/Result.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/Result.aidl
new file mode 100644
index 0000000..f19bf3b
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/Result.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.tv.tuner;
+
+/**
+ * Tuner error codes. Aidl will return these error codes as service specific
+ * errors in EX_SERVICE_SPECIFIC.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum Result {
+    SUCCESS,
+    UNAVAILABLE,
+    NOT_INITIALIZED,
+    INVALID_STATE,
+    INVALID_ARGUMENT,
+    OUT_OF_MEMORY,
+    UNKNOWN_ERROR,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/ScramblingStatus.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/ScramblingStatus.aidl
new file mode 100644
index 0000000..76f56ae
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/ScramblingStatus.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Scrambling Status Type.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum ScramblingStatus {
+    /**
+     * Content’s scrambling status is unknown
+     */
+    UNKNOWN = 1 << 0,
+
+    /**
+     * Content is not scrambled.
+     */
+    NOT_SCRAMBLED = 1 << 1,
+
+    /**
+     * Content is scrambled.
+     */
+    SCRAMBLED = 1 << 2,
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/VideoStreamType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/VideoStreamType.aidl
new file mode 100644
index 0000000..108d986
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/VideoStreamType.aidl
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner;
+
+/**
+ * Video stream coding format.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum VideoStreamType {
+    UNDEFINED,
+
+    /*
+     * ITU-T | ISO/IEC Reserved
+     */
+    RESERVED,
+
+    /*
+     * ISO/IEC 11172
+     */
+    MPEG1,
+
+    /*
+     * ITU-T Rec.H.262 and ISO/IEC 13818-2
+     */
+    MPEG2,
+
+    /*
+     * ISO/IEC 14496-2 (MPEG-4 H.263 based video)
+     */
+    MPEG4P2,
+
+    /*
+     * ITU-T Rec.H.264 and ISO/IEC 14496-10
+     */
+    AVC,
+
+    /*
+     * ITU-T Rec. H.265 and ISO/IEC 23008-2
+     */
+    HEVC,
+
+    /*
+     * Microsoft VC.1
+     */
+    VC1,
+
+    /*
+     * Google VP8
+     */
+    VP8,
+
+    /*
+     * Google VP9
+     */
+    VP9,
+
+    /*
+     * AOMedia Video 1
+     */
+    AV1,
+
+    /*
+     * Chinese Standard
+     */
+    AVS,
+
+    /*
+     * New Chinese Standard
+     */
+    AVS2,
+}
diff --git a/tv/tuner/aidl/default/Android.bp b/tv/tuner/aidl/default/Android.bp
new file mode 100644
index 0000000..cb8f87b
--- /dev/null
+++ b/tv/tuner/aidl/default/Android.bp
@@ -0,0 +1,46 @@
+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.tv.tuner-service.example",
+    relative_install_path: "hw",
+    init_rc: ["tuner-default.rc"],
+    vintf_fragments: ["tuner-default.xml"],
+    vendor: true,
+    compile_multilib: "first",
+    srcs: [
+        "Demux.cpp",
+        "Descrambler.cpp",
+        "Dvr.cpp",
+        "Filter.cpp",
+        "Frontend.cpp",
+        "Lnb.cpp",
+        "TimeFilter.cpp",
+        "Tuner.cpp",
+        "service.cpp",
+    ],
+    static_libs: [
+        "libaidlcommonsupport",
+    ],
+    shared_libs: [
+        "android.hardware.common.fmq-V1-ndk",
+        "android.hardware.tv.tuner-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "libdmabufheap",
+        "libfmq",
+        "libion",
+        "liblog",
+        "libutils",
+    ],
+    header_libs: [
+        "media_plugin_headers",
+    ],
+}
diff --git a/tv/tuner/aidl/default/Demux.cpp b/tv/tuner/aidl/default/Demux.cpp
new file mode 100644
index 0000000..a94b4ad
--- /dev/null
+++ b/tv/tuner/aidl/default/Demux.cpp
@@ -0,0 +1,471 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "android.hardware.tv.tuner-service.example-Demux"
+
+#include <aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.h>
+#include <aidl/android/hardware/tv/tuner/Result.h>
+
+#include <utils/Log.h>
+#include "Demux.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+#define WAIT_TIMEOUT 3000000000
+
+Demux::Demux(int32_t demuxId, std::shared_ptr<Tuner> tuner) {
+    mDemuxId = demuxId;
+    mTuner = tuner;
+}
+
+Demux::~Demux() {
+    close();
+}
+
+::ndk::ScopedAStatus Demux::setFrontendDataSource(int32_t in_frontendId) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mTuner == nullptr) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::NOT_INITIALIZED));
+    }
+
+    mFrontend = mTuner->getFrontendById(in_frontendId);
+    if (mFrontend == nullptr) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_STATE));
+    }
+
+    mTuner->setFrontendAsDemuxSource(in_frontendId, mDemuxId);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Demux::openFilter(const DemuxFilterType& in_type, int32_t in_bufferSize,
+                                       const std::shared_ptr<IFilterCallback>& in_cb,
+                                       std::shared_ptr<IFilter>* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    int64_t filterId;
+    filterId = ++mLastUsedFilterId;
+
+    if (in_cb == nullptr) {
+        ALOGW("[Demux] callback can't be null");
+        *_aidl_return = nullptr;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    std::shared_ptr<Filter> filter = ndk::SharedRefBase::make<Filter>(
+            in_type, filterId, in_bufferSize, in_cb, this->ref<Demux>());
+    if (!filter->createFilterMQ()) {
+        *_aidl_return = nullptr;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::UNKNOWN_ERROR));
+    }
+
+    mFilters[filterId] = filter;
+    if (filter->isPcrFilter()) {
+        mPcrFilterIds.insert(filterId);
+    }
+    bool result = true;
+    if (!filter->isRecordFilter()) {
+        // Only save non-record filters for now. Record filters are saved when the
+        // IDvr.attacheFilter is called.
+        mPlaybackFilterIds.insert(filterId);
+        if (mDvrPlayback != nullptr) {
+            result = mDvrPlayback->addPlaybackFilter(filterId, filter);
+        }
+    }
+
+    if (!result) {
+        *_aidl_return = nullptr;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    *_aidl_return = filter;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Demux::openTimeFilter(std::shared_ptr<ITimeFilter>* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    mTimeFilter = ndk::SharedRefBase::make<TimeFilter>(this->ref<Demux>());
+
+    *_aidl_return = mTimeFilter;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Demux::getAvSyncHwId(const std::shared_ptr<IFilter>& in_filter,
+                                          int32_t* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    int64_t id;
+    ::ndk::ScopedAStatus status;
+
+    status = in_filter->getId64Bit(&id);
+    if (!status.isOk()) {
+        ALOGE("[Demux] Can't get filter Id.");
+        *_aidl_return = -1;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_STATE));
+    }
+
+    if (!mFilters[id]->isMediaFilter()) {
+        ALOGE("[Demux] Given filter is not a media filter.");
+        *_aidl_return = -1;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_STATE));
+    }
+
+    if (!mPcrFilterIds.empty()) {
+        // Return the lowest pcr filter id in the default implementation as the av sync id
+        *_aidl_return = *mPcrFilterIds.begin();
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    ALOGE("[Demux] No PCR filter opened.");
+    *_aidl_return = -1;
+    return ::ndk::ScopedAStatus::fromServiceSpecificError(
+            static_cast<int32_t>(Result::INVALID_STATE));
+}
+
+::ndk::ScopedAStatus Demux::getAvSyncTime(int32_t in_avSyncHwId, int64_t* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mPcrFilterIds.empty()) {
+        *_aidl_return = -1;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_STATE));
+    }
+    if (in_avSyncHwId != *mPcrFilterIds.begin()) {
+        *_aidl_return = -1;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    *_aidl_return = -1;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Demux::close() {
+    ALOGV("%s", __FUNCTION__);
+
+    stopFrontendInput();
+
+    set<int64_t>::iterator it;
+    for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+        mDvrPlayback->removePlaybackFilter(*it);
+    }
+    mPlaybackFilterIds.clear();
+    mRecordFilterIds.clear();
+    mFilters.clear();
+    mLastUsedFilterId = -1;
+    mTuner->removeDemux(mDemuxId);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Demux::openDvr(DvrType in_type, int32_t in_bufferSize,
+                                    const std::shared_ptr<IDvrCallback>& in_cb,
+                                    std::shared_ptr<IDvr>* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (in_cb == nullptr) {
+        ALOGW("[Demux] DVR callback can't be null");
+        *_aidl_return = nullptr;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    set<int64_t>::iterator it;
+    switch (in_type) {
+        case DvrType::PLAYBACK:
+            mDvrPlayback = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
+                                                         this->ref<Demux>());
+            if (!mDvrPlayback->createDvrMQ()) {
+                mDvrPlayback = nullptr;
+                *_aidl_return = mDvrPlayback;
+                return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                        static_cast<int32_t>(Result::UNKNOWN_ERROR));
+            }
+
+            for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+                if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
+                    ALOGE("[Demux] Can't get filter info for DVR playback");
+                    mDvrPlayback = nullptr;
+                    *_aidl_return = mDvrPlayback;
+                    return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                            static_cast<int32_t>(Result::UNKNOWN_ERROR));
+                }
+            }
+
+            *_aidl_return = mDvrPlayback;
+            return ::ndk::ScopedAStatus::ok();
+        case DvrType::RECORD:
+            mDvrRecord = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
+                                                       this->ref<Demux>());
+            if (!mDvrRecord->createDvrMQ()) {
+                mDvrRecord = nullptr;
+                *_aidl_return = mDvrRecord;
+                return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                        static_cast<int32_t>(Result::UNKNOWN_ERROR));
+            }
+
+            *_aidl_return = mDvrRecord;
+            return ::ndk::ScopedAStatus::ok();
+        default:
+            *_aidl_return = nullptr;
+            return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                    static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+}
+
+::ndk::ScopedAStatus Demux::connectCiCam(int32_t in_ciCamId) {
+    ALOGV("%s", __FUNCTION__);
+
+    mCiCamId = in_ciCamId;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Demux::disconnectCiCam() {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Demux::removeFilter(int64_t filterId) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mDvrPlayback != nullptr) {
+        mDvrPlayback->removePlaybackFilter(filterId);
+    }
+    mPlaybackFilterIds.erase(filterId);
+    mRecordFilterIds.erase(filterId);
+    mFilters.erase(filterId);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+void Demux::startBroadcastTsFilter(vector<int8_t> data) {
+    set<int64_t>::iterator it;
+    uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
+    if (DEBUG_DEMUX) {
+        ALOGW("[Demux] start ts filter pid: %d", pid);
+    }
+    for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+        if (pid == mFilters[*it]->getTpid()) {
+            mFilters[*it]->updateFilterOutput(data);
+        }
+    }
+}
+
+void Demux::sendFrontendInputToRecord(vector<int8_t> data) {
+    set<int64_t>::iterator it;
+    if (DEBUG_DEMUX) {
+        ALOGW("[Demux] update record filter output");
+    }
+    for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
+        mFilters[*it]->updateRecordOutput(data);
+    }
+}
+
+void Demux::sendFrontendInputToRecord(vector<int8_t> data, uint16_t pid, uint64_t pts) {
+    sendFrontendInputToRecord(data);
+    set<int64_t>::iterator it;
+    for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
+        if (pid == mFilters[*it]->getTpid()) {
+            mFilters[*it]->updatePts(pts);
+        }
+    }
+}
+
+bool Demux::startBroadcastFilterDispatcher() {
+    set<int64_t>::iterator it;
+
+    // Handle the output data per filter type
+    for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+        if (!mFilters[*it]->startFilterHandler().isOk()) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool Demux::startRecordFilterDispatcher() {
+    set<int64_t>::iterator it;
+
+    for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
+        if (!mFilters[*it]->startRecordFilterHandler().isOk()) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+::ndk::ScopedAStatus Demux::startFilterHandler(int64_t filterId) {
+    return mFilters[filterId]->startFilterHandler();
+}
+
+void Demux::updateFilterOutput(int64_t filterId, vector<int8_t> data) {
+    mFilters[filterId]->updateFilterOutput(data);
+}
+
+void Demux::updateMediaFilterOutput(int64_t filterId, vector<int8_t> data, uint64_t pts) {
+    updateFilterOutput(filterId, data);
+    mFilters[filterId]->updatePts(pts);
+}
+
+uint16_t Demux::getFilterTpid(int64_t filterId) {
+    return mFilters[filterId]->getTpid();
+}
+
+void Demux::startFrontendInputLoop() {
+    ALOGD("[Demux] start frontend on demux");
+    // Stop current Frontend thread loop first, in case the user starts a new
+    // tuning before stopping current tuning.
+    stopFrontendInput();
+    mFrontendInputThreadRunning = true;
+    mFrontendInputThread = std::thread(&Demux::frontendInputThreadLoop, this);
+}
+
+void Demux::frontendInputThreadLoop() {
+    if (!mFrontendInputThreadRunning) {
+        return;
+    }
+
+    if (!mDvrPlayback) {
+        ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
+        mFrontendInputThreadRunning = false;
+        return;
+    }
+
+    while (mFrontendInputThreadRunning) {
+        uint32_t efState = 0;
+        ::android::status_t status = mDvrPlayback->getDvrEventFlag()->wait(
+                static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
+                true /* retry on spurious wake */);
+        if (status != ::android::OK) {
+            ALOGD("[Demux] wait for data ready on the playback FMQ");
+            continue;
+        }
+        if (mDvrPlayback->getSettings().get<DvrSettings::Tag::playback>().dataFormat ==
+            DataFormat::ES) {
+            if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
+                ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
+                break;
+            }
+            continue;
+        }
+        // Our current implementation filter the data and write it into the filter FMQ immediately
+        // after the DATA_READY from the VTS/framework
+        // This is for the non-ES data source, real playback use case handling.
+        if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
+            !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
+            ALOGE("[Demux] playback data failed to be filtered. Ending thread");
+            break;
+        }
+    }
+
+    mFrontendInputThreadRunning = false;
+    ALOGW("[Demux] Frontend Input thread end.");
+}
+
+void Demux::stopFrontendInput() {
+    ALOGD("[Demux] stop frontend on demux");
+    mKeepFetchingDataFromFrontend = false;
+    mFrontendInputThreadRunning = false;
+    if (mFrontendInputThread.joinable()) {
+        mFrontendInputThread.join();
+    }
+}
+
+void Demux::setIsRecording(bool isRecording) {
+    mIsRecording = isRecording;
+}
+
+bool Demux::isRecording() {
+    return mIsRecording;
+}
+
+binder_status_t Demux::dump(int fd, const char** args, uint32_t numArgs) {
+    dprintf(fd, " Demux %d:\n", mDemuxId);
+    dprintf(fd, "  mIsRecording %d\n", mIsRecording);
+    {
+        dprintf(fd, "  Filters:\n");
+        map<int64_t, std::shared_ptr<Filter>>::iterator it;
+        for (it = mFilters.begin(); it != mFilters.end(); it++) {
+            it->second->dump(fd, args, numArgs);
+        }
+    }
+    {
+        dprintf(fd, "  TimeFilter:\n");
+        if (mTimeFilter != nullptr) {
+            mTimeFilter->dump(fd, args, numArgs);
+        }
+    }
+    {
+        dprintf(fd, "  DvrPlayback:\n");
+        if (mDvrPlayback != nullptr) {
+            mDvrPlayback->dump(fd, args, numArgs);
+        }
+    }
+    {
+        dprintf(fd, "  DvrRecord:\n");
+        if (mDvrRecord != nullptr) {
+            mDvrRecord->dump(fd, args, numArgs);
+        }
+    }
+    return STATUS_OK;
+}
+
+bool Demux::attachRecordFilter(int64_t filterId) {
+    if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
+        !mFilters[filterId]->isRecordFilter()) {
+        return false;
+    }
+
+    mRecordFilterIds.insert(filterId);
+    mFilters[filterId]->attachFilterToRecord(mDvrRecord);
+
+    return true;
+}
+
+bool Demux::detachRecordFilter(int64_t filterId) {
+    if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
+        return false;
+    }
+
+    mRecordFilterIds.erase(filterId);
+    mFilters[filterId]->detachFilterFromRecord();
+
+    return true;
+}
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Demux.h b/tv/tuner/aidl/default/Demux.h
new file mode 100644
index 0000000..7f0b0a7
--- /dev/null
+++ b/tv/tuner/aidl/default/Demux.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/BnDemux.h>
+
+#include <fmq/AidlMessageQueue.h>
+#include <math.h>
+#include <atomic>
+#include <set>
+#include <thread>
+
+#include "Dvr.h"
+#include "Filter.h"
+#include "Frontend.h"
+#include "TimeFilter.h"
+#include "Tuner.h"
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::hardware::EventFlag;
+
+using FilterMQ = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+
+class Dvr;
+class Filter;
+class Frontend;
+class TimeFilter;
+class Tuner;
+
+class Demux : public BnDemux {
+  public:
+    Demux(int32_t demuxId, std::shared_ptr<Tuner> tuner);
+    ~Demux();
+
+    ::ndk::ScopedAStatus setFrontendDataSource(int32_t in_frontendId) override;
+    ::ndk::ScopedAStatus openFilter(const DemuxFilterType& in_type, int32_t in_bufferSize,
+                                    const std::shared_ptr<IFilterCallback>& in_cb,
+                                    std::shared_ptr<IFilter>* _aidl_return) override;
+    ::ndk::ScopedAStatus openTimeFilter(std::shared_ptr<ITimeFilter>* _aidl_return) override;
+    ::ndk::ScopedAStatus getAvSyncHwId(const std::shared_ptr<IFilter>& in_filter,
+                                       int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus getAvSyncTime(int32_t in_avSyncHwId, int64_t* _aidl_return) override;
+    ::ndk::ScopedAStatus close() override;
+    ::ndk::ScopedAStatus openDvr(DvrType in_type, int32_t in_bufferSize,
+                                 const std::shared_ptr<IDvrCallback>& in_cb,
+                                 std::shared_ptr<IDvr>* _aidl_return) override;
+    ::ndk::ScopedAStatus connectCiCam(int32_t in_ciCamId) override;
+    ::ndk::ScopedAStatus disconnectCiCam() override;
+
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
+    // Functions interacts with Tuner Service
+    void stopFrontendInput();
+    ::ndk::ScopedAStatus removeFilter(int64_t filterId);
+    bool attachRecordFilter(int64_t filterId);
+    bool detachRecordFilter(int64_t filterId);
+    ::ndk::ScopedAStatus startFilterHandler(int64_t filterId);
+    void updateFilterOutput(int64_t filterId, vector<int8_t> data);
+    void updateMediaFilterOutput(int64_t filterId, vector<int8_t> data, uint64_t pts);
+    uint16_t getFilterTpid(int64_t filterId);
+    void setIsRecording(bool isRecording);
+    bool isRecording();
+    void startFrontendInputLoop();
+
+    /**
+     * A dispatcher to read and dispatch input data to all the started filters.
+     * Each filter handler handles the data filtering/output writing/filterEvent updating.
+     * Note that recording filters are not included.
+     */
+    bool startBroadcastFilterDispatcher();
+    void startBroadcastTsFilter(vector<int8_t> data);
+
+    void sendFrontendInputToRecord(vector<int8_t> data);
+    void sendFrontendInputToRecord(vector<int8_t> data, uint16_t pid, uint64_t pts);
+    bool startRecordFilterDispatcher();
+
+  private:
+    // Tuner service
+    std::shared_ptr<Tuner> mTuner;
+
+    // Frontend source
+    std::shared_ptr<Frontend> mFrontend;
+
+    // A struct that passes the arguments to a newly created filter thread
+    struct ThreadArgs {
+        Demux* user;
+        int64_t filterId;
+    };
+
+    static void* __threadLoopFrontend(void* user);
+    void frontendInputThreadLoop();
+
+    /**
+     * To create a FilterMQ with the next available Filter ID.
+     * Creating Event Flag at the same time.
+     * Add the successfully created/saved FilterMQ into the local list.
+     *
+     * Return false is any of the above processes fails.
+     */
+    void deleteEventFlag();
+    bool readDataFromMQ();
+
+    int32_t mDemuxId = -1;
+    int32_t mCiCamId;
+    set<int64_t> mPcrFilterIds;
+    /**
+     * Record the last used filter id. Initial value is -1.
+     * Filter Id starts with 0.
+     */
+    int64_t mLastUsedFilterId = -1;
+    /**
+     * Record all the used playback filter Ids.
+     * Any removed filter id should be removed from this set.
+     */
+    set<int64_t> mPlaybackFilterIds;
+    /**
+     * Record all the attached record filter Ids.
+     * Any removed filter id should be removed from this set.
+     */
+    set<int64_t> mRecordFilterIds;
+    /**
+     * A list of created Filter sp.
+     * The array number is the filter ID.
+     */
+    std::map<int64_t, std::shared_ptr<Filter>> mFilters;
+
+    /**
+     * Local reference to the opened Timer Filter instance.
+     */
+    std::shared_ptr<TimeFilter> mTimeFilter;
+
+    /**
+     * Local reference to the opened DVR object.
+     */
+    std::shared_ptr<Dvr> mDvrPlayback;
+    std::shared_ptr<Dvr> mDvrRecord;
+
+    // Thread handlers
+    std::thread mFrontendInputThread;
+
+    /**
+     * If a specific filter's writing loop is still running
+     */
+    std::atomic<bool> mFrontendInputThreadRunning;
+    std::atomic<bool> mKeepFetchingDataFromFrontend;
+
+    /**
+     * If the dvr recording is running.
+     */
+    bool mIsRecording = false;
+    /**
+     * Lock to protect writes to the FMQs
+     */
+    std::mutex mWriteLock;
+
+    // temp handle single PES filter
+    // TODO handle mulptiple Pes filters
+    int mPesSizeLeft = 0;
+    vector<uint8_t> mPesOutput;
+
+    const bool DEBUG_DEMUX = false;
+};
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Descrambler.cpp b/tv/tuner/aidl/default/Descrambler.cpp
new file mode 100644
index 0000000..586db73
--- /dev/null
+++ b/tv/tuner/aidl/default/Descrambler.cpp
@@ -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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.tv.tuner-service.example-Descrambler"
+
+#include <aidl/android/hardware/tv/tuner/IFrontendCallback.h>
+#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <utils/Log.h>
+
+#include "Descrambler.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+Descrambler::Descrambler() {}
+
+Descrambler::~Descrambler() {}
+
+::ndk::ScopedAStatus Descrambler::setDemuxSource(int32_t in_demuxId) {
+    ALOGV("%s", __FUNCTION__);
+    if (mDemuxSet) {
+        ALOGW("[   WARN   ] Descrambler has already been set with a demux id %" PRIu32,
+              mSourceDemuxId);
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_STATE));
+    }
+    mDemuxSet = true;
+    mSourceDemuxId = in_demuxId;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Descrambler::setKeyToken(const std::vector<uint8_t>& /* in_keyToken */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Descrambler::addPid(
+        const DemuxPid& /* in_pid */,
+        const std::shared_ptr<IFilter>& /* in_optionalSourceFilter */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Descrambler::removePid(
+        const DemuxPid& /* in_pid */,
+        const std::shared_ptr<IFilter>& /* in_optionalSourceFilter */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Descrambler::close() {
+    ALOGV("%s", __FUNCTION__);
+    mDemuxSet = false;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Descrambler.h b/tv/tuner/aidl/default/Descrambler.h
new file mode 100644
index 0000000..ddf2c1d
--- /dev/null
+++ b/tv/tuner/aidl/default/Descrambler.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/BnDescrambler.h>
+#include <aidl/android/hardware/tv/tuner/ITuner.h>
+#include <inttypes.h>
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+class Descrambler : public BnDescrambler {
+  public:
+    Descrambler();
+
+    ::ndk::ScopedAStatus setDemuxSource(int32_t in_demuxId) override;
+    ::ndk::ScopedAStatus setKeyToken(const std::vector<uint8_t>& in_keyToken) override;
+    ::ndk::ScopedAStatus addPid(const DemuxPid& in_pid,
+                                const std::shared_ptr<IFilter>& in_optionalSourceFilter) override;
+    ::ndk::ScopedAStatus removePid(
+            const DemuxPid& in_pid,
+            const std::shared_ptr<IFilter>& in_optionalSourceFilter) override;
+    ::ndk::ScopedAStatus close() override;
+
+  private:
+    virtual ~Descrambler();
+    int32_t mSourceDemuxId;
+    bool mDemuxSet = false;
+};
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Dvr.cpp b/tv/tuner/aidl/default/Dvr.cpp
new file mode 100644
index 0000000..c591d07
--- /dev/null
+++ b/tv/tuner/aidl/default/Dvr.cpp
@@ -0,0 +1,495 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "android.hardware.tv.tuner-service.example-Dvr"
+
+#include <aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.h>
+#include <aidl/android/hardware/tv/tuner/Result.h>
+
+#include <utils/Log.h>
+#include "Dvr.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+#define WAIT_TIMEOUT 3000000000
+
+Dvr::Dvr(DvrType type, uint32_t bufferSize, const std::shared_ptr<IDvrCallback>& cb,
+         std::shared_ptr<Demux> demux) {
+    mType = type;
+    mBufferSize = bufferSize;
+    mCallback = cb;
+    mDemux = demux;
+}
+
+Dvr::~Dvr() {
+    // make sure thread has joined
+    close();
+}
+
+::ndk::ScopedAStatus Dvr::getQueueDesc(MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue) {
+    ALOGV("%s", __FUNCTION__);
+
+    *out_queue = mDvrMQ->dupeDesc();
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Dvr::configure(const DvrSettings& in_settings) {
+    ALOGV("%s", __FUNCTION__);
+
+    mDvrSettings = in_settings;
+    mDvrConfigured = true;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Dvr::attachFilter(const std::shared_ptr<IFilter>& in_filter) {
+    ALOGV("%s", __FUNCTION__);
+
+    int64_t filterId;
+    ::ndk::ScopedAStatus status = in_filter->getId64Bit(&filterId);
+    if (!status.isOk()) {
+        return status;
+    }
+
+    if (!mDemux->attachRecordFilter(filterId)) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Dvr::detachFilter(const std::shared_ptr<IFilter>& in_filter) {
+    ALOGV("%s", __FUNCTION__);
+
+    int64_t filterId;
+    ::ndk::ScopedAStatus status = in_filter->getId64Bit(&filterId);
+    if (!status.isOk()) {
+        return status;
+    }
+
+    if (!mDemux->detachRecordFilter(filterId)) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Dvr::start() {
+    ALOGV("%s", __FUNCTION__);
+    if (mDvrThreadRunning) {
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    if (!mCallback) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::NOT_INITIALIZED));
+    }
+
+    if (!mDvrConfigured) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_STATE));
+    }
+
+    if (mType == DvrType::PLAYBACK) {
+        mDvrThreadRunning = true;
+        mDvrThread = std::thread(&Dvr::playbackThreadLoop, this);
+    } else if (mType == DvrType::RECORD) {
+        mRecordStatus = RecordStatus::DATA_READY;
+        mDemux->setIsRecording(mType == DvrType::RECORD);
+    }
+
+    // TODO start another thread to send filter status callback to the framework
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Dvr::stop() {
+    ALOGV("%s", __FUNCTION__);
+
+    mDvrThreadRunning = false;
+    if (mDvrThread.joinable()) {
+        mDvrThread.join();
+    }
+    // thread should always be joinable if it is running,
+    // so it should be safe to assume recording stopped.
+    mDemux->setIsRecording(false);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Dvr::flush() {
+    ALOGV("%s", __FUNCTION__);
+
+    mRecordStatus = RecordStatus::DATA_READY;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Dvr::close() {
+    ALOGV("%s", __FUNCTION__);
+
+    stop();
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+bool Dvr::createDvrMQ() {
+    ALOGV("%s", __FUNCTION__);
+
+    // Create a synchronized FMQ that supports blocking read/write
+    unique_ptr<DvrMQ> tmpDvrMQ = unique_ptr<DvrMQ>(new (nothrow) DvrMQ(mBufferSize, true));
+    if (!tmpDvrMQ->isValid()) {
+        ALOGW("[Dvr] Failed to create FMQ of DVR");
+        return false;
+    }
+
+    mDvrMQ = move(tmpDvrMQ);
+
+    if (EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrEventFlag) != ::android::OK) {
+        return false;
+    }
+
+    return true;
+}
+
+EventFlag* Dvr::getDvrEventFlag() {
+    return mDvrEventFlag;
+}
+
+binder_status_t Dvr::dump(int fd, const char** /* args */, uint32_t /* numArgs */) {
+    dprintf(fd, "    Dvr:\n");
+    dprintf(fd, "      mType: %hhd\n", mType);
+    dprintf(fd, "      mDvrThreadRunning: %d\n", (bool)mDvrThreadRunning);
+    return STATUS_OK;
+}
+
+void Dvr::playbackThreadLoop() {
+    ALOGD("[Dvr] playback threadLoop start.");
+
+    while (mDvrThreadRunning) {
+        uint32_t efState = 0;
+        ::android::status_t status =
+                mDvrEventFlag->wait(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY),
+                                    &efState, WAIT_TIMEOUT, true /* retry on spurious wake */);
+        if (status != ::android::OK) {
+            ALOGD("[Dvr] wait for data ready on the playback FMQ");
+            continue;
+        }
+
+        // If the both dvr playback and dvr record are created, the playback will be treated as
+        // the source of the record. isVirtualFrontend set to true would direct the dvr playback
+        // input to the demux record filters or live broadcast filters.
+        bool isRecording = mDemux->isRecording();
+        bool isVirtualFrontend = isRecording;
+
+        if (mDvrSettings.get<DvrSettings::Tag::playback>().dataFormat == DataFormat::ES) {
+            if (!processEsDataOnPlayback(isVirtualFrontend, isRecording)) {
+                ALOGE("[Dvr] playback es data failed to be filtered. Ending thread");
+                break;
+            }
+            maySendPlaybackStatusCallback();
+            continue;
+        }
+
+        // Our current implementation filter the data and write it into the filter FMQ immediately
+        // after the DATA_READY from the VTS/framework
+        // This is for the non-ES data source, real playback use case handling.
+        if (!readPlaybackFMQ(isVirtualFrontend, isRecording) ||
+            !startFilterDispatcher(isVirtualFrontend, isRecording)) {
+            ALOGE("[Dvr] playback data failed to be filtered. Ending thread");
+            break;
+        }
+
+        maySendPlaybackStatusCallback();
+    }
+
+    mDvrThreadRunning = false;
+    ALOGD("[Dvr] playback thread ended.");
+}
+
+void Dvr::maySendPlaybackStatusCallback() {
+    lock_guard<mutex> lock(mPlaybackStatusLock);
+    int availableToRead = mDvrMQ->availableToRead();
+    int availableToWrite = mDvrMQ->availableToWrite();
+
+    PlaybackStatus newStatus =
+            checkPlaybackStatusChange(availableToWrite, availableToRead,
+                                      mDvrSettings.get<DvrSettings::Tag::playback>().highThreshold,
+                                      mDvrSettings.get<DvrSettings::Tag::playback>().lowThreshold);
+    if (mPlaybackStatus != newStatus) {
+        mCallback->onPlaybackStatus(newStatus);
+        mPlaybackStatus = newStatus;
+    }
+}
+
+PlaybackStatus Dvr::checkPlaybackStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
+                                              int64_t highThreshold, int64_t lowThreshold) {
+    if (availableToWrite == 0) {
+        return PlaybackStatus::SPACE_FULL;
+    } else if (availableToRead > highThreshold) {
+        return PlaybackStatus::SPACE_ALMOST_FULL;
+    } else if (availableToRead < lowThreshold) {
+        return PlaybackStatus::SPACE_ALMOST_EMPTY;
+    } else if (availableToRead == 0) {
+        return PlaybackStatus::SPACE_EMPTY;
+    }
+    return mPlaybackStatus;
+}
+
+bool Dvr::readPlaybackFMQ(bool isVirtualFrontend, bool isRecording) {
+    // Read playback data from the input FMQ
+    size_t size = mDvrMQ->availableToRead();
+    int64_t playbackPacketSize = mDvrSettings.get<DvrSettings::Tag::playback>().packetSize;
+    vector<int8_t> dataOutputBuffer;
+    dataOutputBuffer.resize(playbackPacketSize);
+    // Dispatch the packet to the PID matching filter output buffer
+    for (int i = 0; i < size / playbackPacketSize; i++) {
+        if (!mDvrMQ->read(dataOutputBuffer.data(), playbackPacketSize)) {
+            return false;
+        }
+        if (isVirtualFrontend) {
+            if (isRecording) {
+                mDemux->sendFrontendInputToRecord(dataOutputBuffer);
+            } else {
+                mDemux->startBroadcastTsFilter(dataOutputBuffer);
+            }
+        } else {
+            startTpidFilter(dataOutputBuffer);
+        }
+    }
+
+    return true;
+}
+
+bool Dvr::processEsDataOnPlayback(bool isVirtualFrontend, bool isRecording) {
+    // Read ES from the DVR FMQ
+    // Note that currently we only provides ES with metaData in a specific format to be parsed.
+    // The ES size should be smaller than the Playback FMQ size to avoid reading truncated data.
+    int size = mDvrMQ->availableToRead();
+    vector<int8_t> dataOutputBuffer;
+    dataOutputBuffer.resize(size);
+    if (!mDvrMQ->read(dataOutputBuffer.data(), size)) {
+        return false;
+    }
+
+    int metaDataSize = size;
+    int totalFrames = 0;
+    int videoEsDataSize = 0;
+    int audioEsDataSize = 0;
+    int audioPid = 0;
+    int videoPid = 0;
+
+    vector<MediaEsMetaData> esMeta;
+    int videoReadPointer = 0;
+    int audioReadPointer = 0;
+    int frameCount = 0;
+    // Get meta data from the es
+    for (int i = 0; i < metaDataSize; i++) {
+        switch (dataOutputBuffer[i]) {
+            case 'm':
+                metaDataSize = 0;
+                getMetaDataValue(i, dataOutputBuffer.data(), metaDataSize);
+                videoReadPointer = metaDataSize;
+                continue;
+            case 'l':
+                getMetaDataValue(i, dataOutputBuffer.data(), totalFrames);
+                esMeta.resize(totalFrames);
+                continue;
+            case 'V':
+                getMetaDataValue(i, dataOutputBuffer.data(), videoEsDataSize);
+                audioReadPointer = metaDataSize + videoEsDataSize;
+                continue;
+            case 'A':
+                getMetaDataValue(i, dataOutputBuffer.data(), audioEsDataSize);
+                continue;
+            case 'p':
+                if (dataOutputBuffer[++i] == 'a') {
+                    getMetaDataValue(i, dataOutputBuffer.data(), audioPid);
+                } else if (dataOutputBuffer[i] == 'v') {
+                    getMetaDataValue(i, dataOutputBuffer.data(), videoPid);
+                }
+                continue;
+            case 'v':
+            case 'a':
+                if (dataOutputBuffer[i + 1] != ',') {
+                    ALOGE("[Dvr] Invalid format meta data.");
+                    return false;
+                }
+                esMeta[frameCount] = {
+                        .isAudio = dataOutputBuffer[i] == 'a' ? true : false,
+                };
+                i += 5;  // Move to Len
+                getMetaDataValue(i, dataOutputBuffer.data(), esMeta[frameCount].len);
+                if (esMeta[frameCount].isAudio) {
+                    esMeta[frameCount].startIndex = audioReadPointer;
+                    audioReadPointer += esMeta[frameCount].len;
+                } else {
+                    esMeta[frameCount].startIndex = videoReadPointer;
+                    videoReadPointer += esMeta[frameCount].len;
+                }
+                i += 4;  // move to PTS
+                getMetaDataValue(i, dataOutputBuffer.data(), esMeta[frameCount].pts);
+                frameCount++;
+                continue;
+            default:
+                continue;
+        }
+    }
+
+    if (frameCount != totalFrames) {
+        ALOGE("[Dvr] Invalid meta data, frameCount=%d, totalFrames reported=%d", frameCount,
+              totalFrames);
+        return false;
+    }
+
+    if (metaDataSize + audioEsDataSize + videoEsDataSize != size) {
+        ALOGE("[Dvr] Invalid meta data, metaSize=%d, videoSize=%d, audioSize=%d, totolSize=%d",
+              metaDataSize, videoEsDataSize, audioEsDataSize, size);
+        return false;
+    }
+
+    // Read es raw data from the FMQ per meta data built previously
+    vector<int8_t> frameData;
+    map<int64_t, std::shared_ptr<IFilter>>::iterator it;
+    int pid = 0;
+    for (int i = 0; i < totalFrames; i++) {
+        frameData.resize(esMeta[i].len);
+        pid = esMeta[i].isAudio ? audioPid : videoPid;
+        memcpy(frameData.data(), dataOutputBuffer.data() + esMeta[i].startIndex, esMeta[i].len);
+        // Send to the media filters or record filters
+        if (!isRecording) {
+            for (it = mFilters.begin(); it != mFilters.end(); it++) {
+                if (pid == mDemux->getFilterTpid(it->first)) {
+                    mDemux->updateMediaFilterOutput(it->first, frameData,
+                                                    static_cast<uint64_t>(esMeta[i].pts));
+                }
+            }
+        } else {
+            mDemux->sendFrontendInputToRecord(frameData, pid, static_cast<uint64_t>(esMeta[i].pts));
+        }
+        startFilterDispatcher(isVirtualFrontend, isRecording);
+        frameData.clear();
+    }
+
+    return true;
+}
+
+void Dvr::getMetaDataValue(int& index, int8_t* dataOutputBuffer, int& value) {
+    index += 2;  // Move the pointer across the ":" to the value
+    while (dataOutputBuffer[index] != ',' && dataOutputBuffer[index] != '\n') {
+        value = ((dataOutputBuffer[index++] - 48) + value * 10);
+    }
+}
+
+void Dvr::startTpidFilter(vector<int8_t> data) {
+    map<int64_t, std::shared_ptr<IFilter>>::iterator it;
+    for (it = mFilters.begin(); it != mFilters.end(); it++) {
+        uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
+        if (DEBUG_DVR) {
+            ALOGW("[Dvr] start ts filter pid: %d", pid);
+        }
+        if (pid == mDemux->getFilterTpid(it->first)) {
+            mDemux->updateFilterOutput(it->first, data);
+        }
+    }
+}
+
+bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) {
+    if (isVirtualFrontend) {
+        if (isRecording) {
+            return mDemux->startRecordFilterDispatcher();
+        } else {
+            return mDemux->startBroadcastFilterDispatcher();
+        }
+    }
+
+    map<int64_t, std::shared_ptr<IFilter>>::iterator it;
+    // Handle the output data per filter type
+    for (it = mFilters.begin(); it != mFilters.end(); it++) {
+        if (mDemux->startFilterHandler(it->first).isOk()) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool Dvr::writeRecordFMQ(const vector<int8_t>& data) {
+    lock_guard<mutex> lock(mWriteLock);
+    if (mRecordStatus == RecordStatus::OVERFLOW) {
+        ALOGW("[Dvr] stops writing and wait for the client side flushing.");
+        return true;
+    }
+    if (mDvrMQ->write(data.data(), data.size())) {
+        mDvrEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
+        maySendRecordStatusCallback();
+        return true;
+    }
+
+    maySendRecordStatusCallback();
+    return false;
+}
+
+void Dvr::maySendRecordStatusCallback() {
+    lock_guard<mutex> lock(mRecordStatusLock);
+    int availableToRead = mDvrMQ->availableToRead();
+    int availableToWrite = mDvrMQ->availableToWrite();
+
+    RecordStatus newStatus =
+            checkRecordStatusChange(availableToWrite, availableToRead,
+                                    mDvrSettings.get<DvrSettings::Tag::record>().highThreshold,
+                                    mDvrSettings.get<DvrSettings::Tag::record>().lowThreshold);
+    if (mRecordStatus != newStatus) {
+        mCallback->onRecordStatus(newStatus);
+        mRecordStatus = newStatus;
+    }
+}
+
+RecordStatus Dvr::checkRecordStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
+                                          int64_t highThreshold, int64_t lowThreshold) {
+    if (availableToWrite == 0) {
+        return RecordStatus::OVERFLOW;
+    } else if (availableToRead > highThreshold) {
+        return RecordStatus::HIGH_WATER;
+    } else if (availableToRead < lowThreshold) {
+        return RecordStatus::LOW_WATER;
+    }
+    return mRecordStatus;
+}
+
+bool Dvr::addPlaybackFilter(int64_t filterId, std::shared_ptr<IFilter> filter) {
+    mFilters[filterId] = filter;
+    return true;
+}
+
+bool Dvr::removePlaybackFilter(int64_t filterId) {
+    mFilters.erase(filterId);
+    return true;
+}
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Dvr.h b/tv/tuner/aidl/default/Dvr.h
new file mode 100644
index 0000000..6ff71cd
--- /dev/null
+++ b/tv/tuner/aidl/default/Dvr.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/BnDvr.h>
+#include <aidl/android/hardware/tv/tuner/RecordStatus.h>
+
+#include <fmq/AidlMessageQueue.h>
+#include <math.h>
+#include <atomic>
+#include <set>
+#include <thread>
+#include "Demux.h"
+#include "Frontend.h"
+#include "Tuner.h"
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::hardware::EventFlag;
+
+using DvrMQ = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+
+struct MediaEsMetaData {
+    bool isAudio;
+    int startIndex;
+    int len;
+    int pts;
+};
+
+class Demux;
+class Filter;
+class Frontend;
+class Tuner;
+
+class Dvr : public BnDvr {
+  public:
+    Dvr(DvrType type, uint32_t bufferSize, const std::shared_ptr<IDvrCallback>& cb,
+        std::shared_ptr<Demux> demux);
+    ~Dvr();
+
+    ::ndk::ScopedAStatus getQueueDesc(
+            MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue) override;
+    ::ndk::ScopedAStatus configure(const DvrSettings& in_settings) override;
+    ::ndk::ScopedAStatus attachFilter(const std::shared_ptr<IFilter>& in_filter) override;
+    ::ndk::ScopedAStatus detachFilter(const std::shared_ptr<IFilter>& in_filter) override;
+    ::ndk::ScopedAStatus start() override;
+    ::ndk::ScopedAStatus stop() override;
+    ::ndk::ScopedAStatus flush() override;
+    ::ndk::ScopedAStatus close() override;
+
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
+    /**
+     * To create a DvrMQ and its Event Flag.
+     *
+     * Return false is any of the above processes fails.
+     */
+    bool createDvrMQ();
+    bool writeRecordFMQ(const std::vector<int8_t>& data);
+    bool addPlaybackFilter(int64_t filterId, std::shared_ptr<IFilter> filter);
+    bool removePlaybackFilter(int64_t filterId);
+    bool readPlaybackFMQ(bool isVirtualFrontend, bool isRecording);
+    bool processEsDataOnPlayback(bool isVirtualFrontend, bool isRecording);
+    bool startFilterDispatcher(bool isVirtualFrontend, bool isRecording);
+    EventFlag* getDvrEventFlag();
+    DvrSettings getSettings() { return mDvrSettings; }
+
+  private:
+    // Demux service
+    std::shared_ptr<Demux> mDemux;
+
+    DvrType mType;
+    uint32_t mBufferSize;
+    std::shared_ptr<IDvrCallback> mCallback;
+    std::map<int64_t, std::shared_ptr<IFilter>> mFilters;
+
+    void deleteEventFlag();
+    bool readDataFromMQ();
+    void getMetaDataValue(int& index, int8_t* dataOutputBuffer, int& value);
+    void maySendPlaybackStatusCallback();
+    void maySendRecordStatusCallback();
+    PlaybackStatus checkPlaybackStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
+                                             int64_t highThreshold, int64_t lowThreshold);
+    RecordStatus checkRecordStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
+                                         int64_t highThreshold, int64_t lowThreshold);
+    /**
+     * A dispatcher to read and dispatch input data to all the started filters.
+     * Each filter handler handles the data filtering/output writing/filterEvent updating.
+     */
+    void startTpidFilter(vector<int8_t> data);
+    void playbackThreadLoop();
+
+    unique_ptr<DvrMQ> mDvrMQ;
+    EventFlag* mDvrEventFlag;
+    /**
+     * Demux callbacks used on filter events or IO buffer status
+     */
+    bool mDvrConfigured = false;
+    DvrSettings mDvrSettings;
+
+    // Thread handlers
+    std::thread mDvrThread;
+
+    // FMQ status local records
+    PlaybackStatus mPlaybackStatus;
+    RecordStatus mRecordStatus;
+    /**
+     * If a specific filter's writing loop is still running
+     */
+    std::atomic<bool> mDvrThreadRunning;
+
+    /**
+     * Lock to protect writes to the FMQs
+     */
+    std::mutex mWriteLock;
+    /**
+     * Lock to protect writes to the input status
+     */
+    std::mutex mPlaybackStatusLock;
+    std::mutex mRecordStatusLock;
+
+    const bool DEBUG_DVR = false;
+};
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Filter.cpp b/tv/tuner/aidl/default/Filter.cpp
new file mode 100644
index 0000000..769ebe2
--- /dev/null
+++ b/tv/tuner/aidl/default/Filter.cpp
@@ -0,0 +1,1296 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "android.hardware.tv.tuner-service.example-Filter"
+
+#include <BufferAllocator/BufferAllocator.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterMonitorEventType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.h>
+#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <inttypes.h>
+#include <utils/Log.h>
+
+#include "Filter.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+#define WAIT_TIMEOUT 3000000000
+
+FilterCallbackScheduler::FilterCallbackScheduler(const std::shared_ptr<IFilterCallback>& cb)
+    : mCallback(cb),
+      mIsConditionMet(false),
+      mDataLength(0),
+      mTimeDelayInMs(0),
+      mDataSizeDelayInBytes(0) {
+    start();
+}
+
+FilterCallbackScheduler::~FilterCallbackScheduler() {
+    stop();
+}
+
+void FilterCallbackScheduler::onFilterEvent(DemuxFilterEvent&& event) {
+    std::unique_lock<std::mutex> lock(mLock);
+    mCallbackBuffer.push_back(std::move(event));
+    mDataLength += getDemuxFilterEventDataLength(event);
+
+    if (isDataSizeDelayConditionMetLocked()) {
+        mIsConditionMet = true;
+        // unlock, so thread is not immediately blocked when it is notified.
+        lock.unlock();
+        mCv.notify_all();
+    }
+}
+
+void FilterCallbackScheduler::onFilterStatus(const DemuxFilterStatus& status) {
+    if (mCallback) {
+        mCallback->onFilterStatus(status);
+    }
+}
+
+void FilterCallbackScheduler::flushEvents() {
+    std::unique_lock<std::mutex> lock(mLock);
+    mCallbackBuffer.clear();
+    mDataLength = 0;
+}
+
+void FilterCallbackScheduler::setTimeDelayHint(int timeDelay) {
+    std::unique_lock<std::mutex> lock(mLock);
+    mTimeDelayInMs = timeDelay;
+    // always notify condition variable to update timeout
+    mIsConditionMet = true;
+    lock.unlock();
+    mCv.notify_all();
+}
+
+void FilterCallbackScheduler::setDataSizeDelayHint(int dataSizeDelay) {
+    std::unique_lock<std::mutex> lock(mLock);
+    mDataSizeDelayInBytes = dataSizeDelay;
+    if (isDataSizeDelayConditionMetLocked()) {
+        mIsConditionMet = true;
+        lock.unlock();
+        mCv.notify_all();
+    }
+}
+
+bool FilterCallbackScheduler::hasCallbackRegistered() const {
+    return mCallback != nullptr;
+}
+
+void FilterCallbackScheduler::start() {
+    mIsRunning = true;
+    mCallbackThread = std::thread(&FilterCallbackScheduler::threadLoop, this);
+}
+
+void FilterCallbackScheduler::stop() {
+    mIsRunning = false;
+    if (mCallbackThread.joinable()) {
+        {
+            std::lock_guard<std::mutex> lock(mLock);
+            mIsConditionMet = true;
+        }
+        mCv.notify_all();
+        mCallbackThread.join();
+    }
+}
+
+void FilterCallbackScheduler::threadLoop() {
+    while (mIsRunning) {
+        threadLoopOnce();
+    }
+}
+
+void FilterCallbackScheduler::threadLoopOnce() {
+    std::unique_lock<std::mutex> lock(mLock);
+    if (mTimeDelayInMs > 0) {
+        // Note: predicate protects from lost and spurious wakeups
+        mCv.wait_for(lock, std::chrono::milliseconds(mTimeDelayInMs),
+                     [this] { return mIsConditionMet; });
+    } else {
+        // Note: predicate protects from lost and spurious wakeups
+        mCv.wait(lock, [this] { return mIsConditionMet; });
+    }
+    mIsConditionMet = false;
+
+    // condition_variable wait locks mutex on timeout / notify
+    // Note: if stop() has been called in the meantime, do not send more filter
+    // events.
+    if (mIsRunning && !mCallbackBuffer.empty()) {
+        if (mCallback) {
+            mCallback->onFilterEvent(mCallbackBuffer);
+        }
+        mCallbackBuffer.clear();
+        mDataLength = 0;
+    }
+}
+
+// mLock needs to be held to call this function
+bool FilterCallbackScheduler::isDataSizeDelayConditionMetLocked() {
+    if (mDataSizeDelayInBytes == 0) {
+        // Data size delay is disabled.
+        if (mTimeDelayInMs == 0) {
+            // Events should only be sent immediately if time delay is disabled
+            // as well.
+            return true;
+        }
+        return false;
+    }
+
+    // Data size delay is enabled.
+    return mDataLength >= mDataSizeDelayInBytes;
+}
+
+int FilterCallbackScheduler::getDemuxFilterEventDataLength(const DemuxFilterEvent& event) {
+    // there is a risk that dataLength could be a negative value, but it
+    // *should* be safe to assume that it is always positive.
+    switch (event.getTag()) {
+        case DemuxFilterEvent::Tag::section:
+            return event.get<DemuxFilterEvent::Tag::section>().dataLength;
+        case DemuxFilterEvent::Tag::media:
+            return event.get<DemuxFilterEvent::Tag::media>().dataLength;
+        case DemuxFilterEvent::Tag::pes:
+            return event.get<DemuxFilterEvent::Tag::pes>().dataLength;
+        case DemuxFilterEvent::Tag::download:
+            return event.get<DemuxFilterEvent::Tag::download>().dataLength;
+        case DemuxFilterEvent::Tag::ipPayload:
+            return event.get<DemuxFilterEvent::Tag::ipPayload>().dataLength;
+
+        case DemuxFilterEvent::Tag::tsRecord:
+        case DemuxFilterEvent::Tag::mmtpRecord:
+        case DemuxFilterEvent::Tag::temi:
+        case DemuxFilterEvent::Tag::monitorEvent:
+        case DemuxFilterEvent::Tag::startId:
+            // these events do not include a payload and should therefore return
+            // 0.
+            // do not add a default option, so this will not compile when new types
+            // are added.
+            return 0;
+    }
+}
+
+Filter::Filter(DemuxFilterType type, int64_t filterId, uint32_t bufferSize,
+               const std::shared_ptr<IFilterCallback>& cb, std::shared_ptr<Demux> demux)
+    : mDemux(demux),
+      mCallbackScheduler(cb),
+      mFilterId(filterId),
+      mBufferSize(bufferSize),
+      mType(type) {
+    switch (mType.mainType) {
+        case DemuxFilterMainType::TS:
+            if (mType.subType.get<DemuxFilterSubType::Tag::tsFilterType>() ==
+                        DemuxTsFilterType::AUDIO ||
+                mType.subType.get<DemuxFilterSubType::Tag::tsFilterType>() ==
+                        DemuxTsFilterType::VIDEO) {
+                mIsMediaFilter = true;
+            }
+            if (mType.subType.get<DemuxFilterSubType::Tag::tsFilterType>() ==
+                DemuxTsFilterType::PCR) {
+                mIsPcrFilter = true;
+            }
+            if (mType.subType.get<DemuxFilterSubType::Tag::tsFilterType>() ==
+                DemuxTsFilterType::RECORD) {
+                mIsRecordFilter = true;
+            }
+            break;
+        case DemuxFilterMainType::MMTP:
+            if (mType.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>() ==
+                        DemuxMmtpFilterType::AUDIO ||
+                mType.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>() ==
+                        DemuxMmtpFilterType::VIDEO) {
+                mIsMediaFilter = true;
+            }
+            if (mType.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>() ==
+                DemuxMmtpFilterType::RECORD) {
+                mIsRecordFilter = true;
+            }
+            break;
+        case DemuxFilterMainType::IP:
+            break;
+        case DemuxFilterMainType::TLV:
+            break;
+        case DemuxFilterMainType::ALP:
+            break;
+        default:
+            break;
+    }
+}
+
+Filter::~Filter() {
+    close();
+}
+
+::ndk::ScopedAStatus Filter::getId64Bit(int64_t* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    *_aidl_return = mFilterId;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::getId(int32_t* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    *_aidl_return = static_cast<int32_t>(mFilterId);
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::setDataSource(const std::shared_ptr<IFilter>& in_filter) {
+    ALOGV("%s", __FUNCTION__);
+
+    mDataSource = in_filter;
+    mIsDataSourceDemux = false;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::setDelayHint(const FilterDelayHint& in_hint) {
+    if (mIsMediaFilter) {
+        // delay hint is not supported for media filters
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    ALOGV("%s", __FUNCTION__);
+    if (in_hint.hintValue < 0) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    switch (in_hint.hintType) {
+        case FilterDelayHintType::TIME_DELAY_IN_MS:
+            mCallbackScheduler.setTimeDelayHint(in_hint.hintValue);
+            break;
+        case FilterDelayHintType::DATA_SIZE_DELAY_IN_BYTES:
+            mCallbackScheduler.setDataSizeDelayHint(in_hint.hintValue);
+            break;
+        default:
+            return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                    static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::getQueueDesc(MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue) {
+    ALOGV("%s", __FUNCTION__);
+
+    mIsUsingFMQ = mIsRecordFilter ? false : true;
+
+    *out_queue = mFilterMQ->dupeDesc();
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::configure(const DemuxFilterSettings& in_settings) {
+    ALOGV("%s", __FUNCTION__);
+
+    mFilterSettings = in_settings;
+    switch (mType.mainType) {
+        case DemuxFilterMainType::TS:
+            mTpid = in_settings.get<DemuxFilterSettings::Tag::ts>().tpid;
+            break;
+        case DemuxFilterMainType::MMTP:
+            break;
+        case DemuxFilterMainType::IP:
+            break;
+        case DemuxFilterMainType::TLV:
+            break;
+        case DemuxFilterMainType::ALP:
+            break;
+        default:
+            break;
+    }
+
+    mConfigured = true;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::start() {
+    ALOGV("%s", __FUNCTION__);
+    mFilterThreadRunning = true;
+    std::vector<DemuxFilterEvent> events;
+    // All the filter event callbacks in start are for testing purpose.
+    switch (mType.mainType) {
+        case DemuxFilterMainType::TS:
+            createMediaEvent(events);
+            createTsRecordEvent(events);
+            createTemiEvent(events);
+            break;
+        case DemuxFilterMainType::MMTP:
+            createDownloadEvent(events);
+            createMmtpRecordEvent(events);
+            break;
+        case DemuxFilterMainType::IP:
+            createSectionEvent(events);
+            createIpPayloadEvent(events);
+            break;
+        case DemuxFilterMainType::TLV:
+            createMonitorEvent(events);
+            break;
+        case DemuxFilterMainType::ALP:
+            createMonitorEvent(events);
+            break;
+        default:
+            break;
+    }
+
+    for (auto&& event : events) {
+        mCallbackScheduler.onFilterEvent(std::move(event));
+    }
+
+    return startFilterLoop();
+}
+
+::ndk::ScopedAStatus Filter::stop() {
+    ALOGV("%s", __FUNCTION__);
+
+    mFilterThreadRunning = false;
+    if (mFilterThread.joinable()) {
+        mFilterThread.join();
+    }
+
+    mCallbackScheduler.flushEvents();
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::flush() {
+    ALOGV("%s", __FUNCTION__);
+
+    // temp implementation to flush the FMQ
+    int size = mFilterMQ->availableToRead();
+    int8_t* buffer = new int8_t[size];
+    mFilterMQ->read(buffer, size);
+    delete[] buffer;
+    mFilterStatus = DemuxFilterStatus::DATA_READY;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::releaseAvHandle(const NativeHandle& in_avMemory, int64_t in_avDataId) {
+    ALOGV("%s", __FUNCTION__);
+
+    if ((mSharedAvMemHandle != nullptr) && (in_avMemory.fds.size() > 0) &&
+        (sameFile(in_avMemory.fds[0].get(), mSharedAvMemHandle->data[0]))) {
+        freeSharedAvHandle();
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    if (mDataId2Avfd.find(in_avDataId) == mDataId2Avfd.end()) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    ::close(mDataId2Avfd[in_avDataId]);
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::close() {
+    ALOGV("%s", __FUNCTION__);
+
+    stop();
+
+    return mDemux->removeFilter(mFilterId);
+}
+
+::ndk::ScopedAStatus Filter::configureIpCid(int32_t in_ipCid) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mType.mainType != DemuxFilterMainType::IP) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_STATE));
+    }
+
+    mCid = in_ipCid;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::getAvSharedHandle(NativeHandle* out_avMemory, int64_t* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (!mIsMediaFilter) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_STATE));
+    }
+
+    if (mSharedAvMemHandle != nullptr) {
+        *out_avMemory = ::android::dupToAidl(mSharedAvMemHandle);
+        *_aidl_return = BUFFER_SIZE_16M;
+        mUsingSharedAvMem = true;
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    int av_fd = createAvIonFd(BUFFER_SIZE_16M);
+    if (av_fd < 0) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::OUT_OF_MEMORY));
+    }
+
+    mSharedAvMemHandle = createNativeHandle(av_fd);
+    if (mSharedAvMemHandle == nullptr) {
+        ::close(av_fd);
+        *_aidl_return = 0;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::UNKNOWN_ERROR));
+    }
+    ::close(av_fd);
+    mUsingSharedAvMem = true;
+
+    *out_avMemory = ::android::dupToAidl(mSharedAvMemHandle);
+    *_aidl_return = BUFFER_SIZE_16M;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::configureAvStreamType(const AvStreamType& in_avStreamType) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (!mIsMediaFilter) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    switch (in_avStreamType.getTag()) {
+        case AvStreamType::Tag::audio:
+            mAudioStreamType =
+                    static_cast<uint32_t>(in_avStreamType.get<AvStreamType::Tag::audio>());
+            break;
+        case AvStreamType::Tag::video:
+            mVideoStreamType =
+                    static_cast<uint32_t>(in_avStreamType.get<AvStreamType::Tag::video>());
+            break;
+        default:
+            break;
+    }
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::configureMonitorEvent(int in_monitorEventTypes) {
+    ALOGV("%s", __FUNCTION__);
+
+    int32_t newScramblingStatus =
+            in_monitorEventTypes &
+            static_cast<int32_t>(DemuxFilterMonitorEventType::SCRAMBLING_STATUS);
+    int32_t newIpCid =
+            in_monitorEventTypes & static_cast<int32_t>(DemuxFilterMonitorEventType::IP_CID_CHANGE);
+
+    // if scrambling status monitoring flipped, record the new state and send msg on enabling
+    if (newScramblingStatus ^ mScramblingStatusMonitored) {
+        mScramblingStatusMonitored = newScramblingStatus;
+        if (mScramblingStatusMonitored) {
+            if (mCallbackScheduler.hasCallbackRegistered()) {
+                // Assuming current status is always NOT_SCRAMBLED
+                auto monitorEvent = DemuxFilterMonitorEvent::make<
+                        DemuxFilterMonitorEvent::Tag::scramblingStatus>(
+                        ScramblingStatus::NOT_SCRAMBLED);
+                auto event =
+                        DemuxFilterEvent::make<DemuxFilterEvent::Tag::monitorEvent>(monitorEvent);
+                mCallbackScheduler.onFilterEvent(std::move(event));
+            } else {
+                return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                        static_cast<int32_t>(Result::INVALID_STATE));
+            }
+        }
+    }
+
+    // if ip cid monitoring flipped, record the new state and send msg on enabling
+    if (newIpCid ^ mIpCidMonitored) {
+        mIpCidMonitored = newIpCid;
+        if (mIpCidMonitored) {
+            if (mCallbackScheduler.hasCallbackRegistered()) {
+                // Return random cid
+                auto monitorEvent =
+                        DemuxFilterMonitorEvent::make<DemuxFilterMonitorEvent::Tag::cid>(1);
+                auto event =
+                        DemuxFilterEvent::make<DemuxFilterEvent::Tag::monitorEvent>(monitorEvent);
+                mCallbackScheduler.onFilterEvent(std::move(event));
+            } else {
+                return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                        static_cast<int32_t>(Result::INVALID_STATE));
+            }
+        }
+    }
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+bool Filter::createFilterMQ() {
+    ALOGV("%s", __FUNCTION__);
+
+    // Create a synchronized FMQ that supports blocking read/write
+    std::unique_ptr<FilterMQ> tmpFilterMQ =
+            std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(mBufferSize, true));
+    if (!tmpFilterMQ->isValid()) {
+        ALOGW("[Filter] Failed to create FMQ of filter with id: %" PRIu64, mFilterId);
+        return false;
+    }
+
+    mFilterMQ = std::move(tmpFilterMQ);
+
+    if (EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterEventsFlag) !=
+        ::android::OK) {
+        return false;
+    }
+
+    return true;
+}
+
+::ndk::ScopedAStatus Filter::startFilterLoop() {
+    mFilterThread = std::thread(&Filter::filterThreadLoop, this);
+    return ::ndk::ScopedAStatus::ok();
+}
+
+void Filter::filterThreadLoop() {
+    if (!mFilterThreadRunning) {
+        return;
+    }
+
+    ALOGD("[Filter] filter %" PRIu64 " threadLoop start.", mFilterId);
+
+    // For the first time of filter output, implementation needs to send the filter
+    // Event Callback without waiting for the DATA_CONSUMED to init the process.
+    while (mFilterThreadRunning) {
+        std::unique_lock<std::mutex> lock(mFilterEventsLock);
+        if (mFilterEvents.size() == 0) {
+            lock.unlock();
+            if (DEBUG_FILTER) {
+                ALOGD("[Filter] wait for filter data output.");
+            }
+            usleep(1000 * 1000);
+            continue;
+        }
+
+        // After successfully write, send a callback and wait for the read to be done
+        if (mCallbackScheduler.hasCallbackRegistered()) {
+            if (mConfigured) {
+                auto startEvent =
+                        DemuxFilterEvent::make<DemuxFilterEvent::Tag::startId>(mStartId++);
+                mCallbackScheduler.onFilterEvent(std::move(startEvent));
+                mConfigured = false;
+            }
+
+            // lock is still being held
+            for (auto&& event : mFilterEvents) {
+                mCallbackScheduler.onFilterEvent(std::move(event));
+            }
+        } else {
+            ALOGD("[Filter] filter callback is not configured yet.");
+            mFilterThreadRunning = false;
+            return;
+        }
+
+        mFilterEvents.clear();
+        mFilterStatus = DemuxFilterStatus::DATA_READY;
+        mCallbackScheduler.onFilterStatus(mFilterStatus);
+        break;
+    }
+
+    while (mFilterThreadRunning) {
+        uint32_t efState = 0;
+        // We do not wait for the last round of written data to be read to finish the thread
+        // because the VTS can verify the reading itself.
+        for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
+            if (!mFilterThreadRunning) {
+                break;
+            }
+            while (mFilterThreadRunning && mIsUsingFMQ) {
+                ::android::status_t status = mFilterEventsFlag->wait(
+                        static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
+                        WAIT_TIMEOUT, true /* retry on spurious wake */);
+                if (status != ::android::OK) {
+                    ALOGD("[Filter] wait for data consumed");
+                    continue;
+                }
+                break;
+            }
+
+            maySendFilterStatusCallback();
+
+            while (mFilterThreadRunning) {
+                std::lock_guard<std::mutex> lock(mFilterEventsLock);
+                if (mFilterEvents.size() == 0) {
+                    continue;
+                }
+                // After successfully write, send a callback and wait for the read to be done
+                for (auto&& event : mFilterEvents) {
+                    mCallbackScheduler.onFilterEvent(std::move(event));
+                }
+                mFilterEvents.clear();
+                break;
+            }
+            // We do not wait for the last read to be done
+            // VTS can verify the read result itself.
+            if (i == SECTION_WRITE_COUNT - 1) {
+                ALOGD("[Filter] filter %" PRIu64 " writing done. Ending thread", mFilterId);
+                break;
+            }
+        }
+        break;
+    }
+    ALOGD("[Filter] filter thread ended.");
+}
+
+void Filter::freeSharedAvHandle() {
+    if (!mIsMediaFilter) {
+        return;
+    }
+    native_handle_close(mSharedAvMemHandle);
+    native_handle_delete(mSharedAvMemHandle);
+    mSharedAvMemHandle = nullptr;
+}
+
+binder_status_t Filter::dump(int fd, const char** /* args */, uint32_t /* numArgs */) {
+    dprintf(fd, "    Filter %" PRIu64 ":\n", mFilterId);
+    dprintf(fd, "      Main type: %d\n", mType.mainType);
+    dprintf(fd, "      mIsMediaFilter: %d\n", mIsMediaFilter);
+    dprintf(fd, "      mIsPcrFilter: %d\n", mIsPcrFilter);
+    dprintf(fd, "      mIsRecordFilter: %d\n", mIsRecordFilter);
+    dprintf(fd, "      mIsUsingFMQ: %d\n", mIsUsingFMQ);
+    dprintf(fd, "      mFilterThreadRunning: %d\n", (bool)mFilterThreadRunning);
+    return STATUS_OK;
+}
+
+void Filter::maySendFilterStatusCallback() {
+    if (!mIsUsingFMQ) {
+        return;
+    }
+    std::lock_guard<std::mutex> lock(mFilterStatusLock);
+    int availableToRead = mFilterMQ->availableToRead();
+    int availableToWrite = mFilterMQ->availableToWrite();
+    int fmqSize = mFilterMQ->getQuantumCount();
+
+    DemuxFilterStatus newStatus = checkFilterStatusChange(
+            availableToWrite, availableToRead, ceil(fmqSize * 0.75), ceil(fmqSize * 0.25));
+    if (mFilterStatus != newStatus) {
+        mCallbackScheduler.onFilterStatus(newStatus);
+        mFilterStatus = newStatus;
+    }
+}
+
+DemuxFilterStatus Filter::checkFilterStatusChange(uint32_t availableToWrite,
+                                                  uint32_t availableToRead, uint32_t highThreshold,
+                                                  uint32_t lowThreshold) {
+    if (availableToWrite == 0) {
+        return DemuxFilterStatus::OVERFLOW;
+    } else if (availableToRead > highThreshold) {
+        return DemuxFilterStatus::HIGH_WATER;
+    } else if (availableToRead < lowThreshold) {
+        return DemuxFilterStatus::LOW_WATER;
+    }
+    return mFilterStatus;
+}
+
+uint16_t Filter::getTpid() {
+    return mTpid;
+}
+
+void Filter::updateFilterOutput(vector<int8_t>& data) {
+    std::lock_guard<std::mutex> lock(mFilterOutputLock);
+    mFilterOutput.insert(mFilterOutput.end(), data.begin(), data.end());
+}
+
+void Filter::updatePts(uint64_t pts) {
+    std::lock_guard<std::mutex> lock(mFilterOutputLock);
+    mPts = pts;
+}
+
+void Filter::updateRecordOutput(vector<int8_t>& data) {
+    std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
+    mRecordFilterOutput.insert(mRecordFilterOutput.end(), data.begin(), data.end());
+}
+
+::ndk::ScopedAStatus Filter::startFilterHandler() {
+    std::lock_guard<std::mutex> lock(mFilterOutputLock);
+    switch (mType.mainType) {
+        case DemuxFilterMainType::TS:
+            switch (mType.subType.get<DemuxFilterSubType::Tag::tsFilterType>()) {
+                case DemuxTsFilterType::UNDEFINED:
+                    break;
+                case DemuxTsFilterType::SECTION:
+                    startSectionFilterHandler();
+                    break;
+                case DemuxTsFilterType::PES:
+                    startPesFilterHandler();
+                    break;
+                case DemuxTsFilterType::TS:
+                    startTsFilterHandler();
+                    break;
+                case DemuxTsFilterType::AUDIO:
+                case DemuxTsFilterType::VIDEO:
+                    startMediaFilterHandler();
+                    break;
+                case DemuxTsFilterType::PCR:
+                    startPcrFilterHandler();
+                    break;
+                case DemuxTsFilterType::TEMI:
+                    startTemiFilterHandler();
+                    break;
+                default:
+                    break;
+            }
+            break;
+        case DemuxFilterMainType::MMTP:
+            /*mmtpSettings*/
+            break;
+        case DemuxFilterMainType::IP:
+            /*ipSettings*/
+            break;
+        case DemuxFilterMainType::TLV:
+            /*tlvSettings*/
+            break;
+        case DemuxFilterMainType::ALP:
+            /*alpSettings*/
+            break;
+        default:
+            break;
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::startSectionFilterHandler() {
+    if (mFilterOutput.empty()) {
+        return ::ndk::ScopedAStatus::ok();
+    }
+    if (!writeSectionsAndCreateEvent(mFilterOutput)) {
+        ALOGD("[Filter] filter %" PRIu64 " fails to write into FMQ. Ending thread", mFilterId);
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::UNKNOWN_ERROR));
+    }
+
+    mFilterOutput.clear();
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::startPesFilterHandler() {
+    if (mFilterOutput.empty()) {
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    for (int i = 0; i < mFilterOutput.size(); i += 188) {
+        if (mPesSizeLeft == 0) {
+            uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) |
+                              mFilterOutput[i + 6];
+            if (DEBUG_FILTER) {
+                ALOGD("[Filter] prefix %d", prefix);
+            }
+            if (prefix == 0x000001) {
+                // TODO handle mulptiple Pes filters
+                mPesSizeLeft = (mFilterOutput[i + 8] << 8) | mFilterOutput[i + 9];
+                mPesSizeLeft += 6;
+                if (DEBUG_FILTER) {
+                    ALOGD("[Filter] pes data length %d", mPesSizeLeft);
+                }
+            } else {
+                continue;
+            }
+        }
+
+        int endPoint = min(184, mPesSizeLeft);
+        // append data and check size
+        vector<int8_t>::const_iterator first = mFilterOutput.begin() + i + 4;
+        vector<int8_t>::const_iterator last = mFilterOutput.begin() + i + 4 + endPoint;
+        mPesOutput.insert(mPesOutput.end(), first, last);
+        // size does not match then continue
+        mPesSizeLeft -= endPoint;
+        if (DEBUG_FILTER) {
+            ALOGD("[Filter] pes data left %d", mPesSizeLeft);
+        }
+        if (mPesSizeLeft > 0) {
+            continue;
+        }
+        // size match then create event
+        if (!writeDataToFilterMQ(mPesOutput)) {
+            ALOGD("[Filter] pes data write failed");
+            mFilterOutput.clear();
+            return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                    static_cast<int32_t>(Result::INVALID_ARGUMENT));
+        }
+        maySendFilterStatusCallback();
+        DemuxFilterPesEvent pesEvent;
+        pesEvent = {
+                // temp dump meta data
+                .streamId = static_cast<int32_t>(mPesOutput[3]),
+                .dataLength = static_cast<int32_t>(mPesOutput.size()),
+        };
+        if (DEBUG_FILTER) {
+            ALOGD("[Filter] assembled pes data length %d", pesEvent.dataLength);
+        }
+
+        {
+            std::lock_guard<std::mutex> lock(mFilterEventsLock);
+            mFilterEvents.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::pes>(pesEvent));
+        }
+
+        mPesOutput.clear();
+    }
+
+    mFilterOutput.clear();
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::startTsFilterHandler() {
+    // TODO handle starting TS filter
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::startMediaFilterHandler() {
+    if (mFilterOutput.empty()) {
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    ::ndk::ScopedAStatus result;
+    if (mPts) {
+        result = createMediaFilterEventWithIon(mFilterOutput);
+        if (result.isOk()) {
+            mFilterOutput.clear();
+        }
+        return result;
+    }
+
+    for (int i = 0; i < mFilterOutput.size(); i += 188) {
+        if (mPesSizeLeft == 0) {
+            uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) |
+                              mFilterOutput[i + 6];
+            if (DEBUG_FILTER) {
+                ALOGD("[Filter] prefix %d", prefix);
+            }
+            if (prefix == 0x000001) {
+                // TODO handle mulptiple Pes filters
+                mPesSizeLeft = (mFilterOutput[i + 8] << 8) | mFilterOutput[i + 9];
+                mPesSizeLeft += 6;
+                if (DEBUG_FILTER) {
+                    ALOGD("[Filter] pes data length %d", mPesSizeLeft);
+                }
+            } else {
+                continue;
+            }
+        }
+
+        int endPoint = min(184, mPesSizeLeft);
+        // append data and check size
+        vector<int8_t>::const_iterator first = mFilterOutput.begin() + i + 4;
+        vector<int8_t>::const_iterator last = mFilterOutput.begin() + i + 4 + endPoint;
+        mPesOutput.insert(mPesOutput.end(), first, last);
+        // size does not match then continue
+        mPesSizeLeft -= endPoint;
+        if (DEBUG_FILTER) {
+            ALOGD("[Filter] pes data left %d", mPesSizeLeft);
+        }
+        if (mPesSizeLeft > 0 || mAvBufferCopyCount++ < 10) {
+            continue;
+        }
+
+        result = createMediaFilterEventWithIon(mPesOutput);
+        if (result.isOk()) {
+            return result;
+        }
+    }
+
+    mFilterOutput.clear();
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::createMediaFilterEventWithIon(vector<int8_t>& output) {
+    if (mUsingSharedAvMem) {
+        if (mSharedAvMemHandle == nullptr) {
+            return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                    static_cast<int32_t>(Result::UNKNOWN_ERROR));
+        }
+        return createShareMemMediaEvents(output);
+    }
+
+    return createIndependentMediaEvents(output);
+}
+
+::ndk::ScopedAStatus Filter::startRecordFilterHandler() {
+    std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
+    if (mRecordFilterOutput.empty()) {
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    if (mDvr == nullptr || !mDvr->writeRecordFMQ(mRecordFilterOutput)) {
+        ALOGD("[Filter] dvr fails to write into record FMQ.");
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::UNKNOWN_ERROR));
+    }
+
+    DemuxFilterTsRecordEvent recordEvent;
+    recordEvent = {
+            .byteNumber = static_cast<int64_t>(mRecordFilterOutput.size()),
+            .pts = (mPts == 0) ? static_cast<int64_t>(time(NULL)) * 900000 : mPts,
+            .firstMbInSlice = 0,  // random address
+    };
+
+    {
+        std::lock_guard<std::mutex> lock(mFilterEventsLock);
+        mFilterEvents.push_back(
+                DemuxFilterEvent::make<DemuxFilterEvent::Tag::tsRecord>(recordEvent));
+    }
+
+    mRecordFilterOutput.clear();
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::startPcrFilterHandler() {
+    // TODO handle starting PCR filter
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::startTemiFilterHandler() {
+    // TODO handle starting TEMI filter
+    return ::ndk::ScopedAStatus::ok();
+}
+
+bool Filter::writeSectionsAndCreateEvent(vector<int8_t>& data) {
+    // TODO check how many sections has been read
+    ALOGD("[Filter] section handler");
+    if (!writeDataToFilterMQ(data)) {
+        return false;
+    }
+    DemuxFilterSectionEvent secEvent;
+    secEvent = {
+            // temp dump meta data
+            .tableId = 0,
+            .version = 1,
+            .sectionNum = 1,
+            .dataLength = static_cast<int32_t>(data.size()),
+    };
+
+    {
+        std::lock_guard<std::mutex> lock(mFilterEventsLock);
+        mFilterEvents.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::section>(secEvent));
+    }
+
+    return true;
+}
+
+bool Filter::writeDataToFilterMQ(const std::vector<int8_t>& data) {
+    std::lock_guard<std::mutex> lock(mWriteLock);
+    if (mFilterMQ->write(data.data(), data.size())) {
+        return true;
+    }
+    return false;
+}
+
+void Filter::attachFilterToRecord(const std::shared_ptr<Dvr> dvr) {
+    mDvr = dvr;
+}
+
+void Filter::detachFilterFromRecord() {
+    mDvr = nullptr;
+}
+
+int Filter::createAvIonFd(int size) {
+    // Create an DMA-BUF fd and allocate an av fd mapped to a buffer to it.
+    auto buffer_allocator = std::make_unique<BufferAllocator>();
+    if (!buffer_allocator) {
+        ALOGE("[Filter] Unable to create BufferAllocator object");
+        return -1;
+    }
+    int av_fd = -1;
+    av_fd = buffer_allocator->Alloc("system-uncached", size);
+    if (av_fd < 0) {
+        ALOGE("[Filter] Failed to create av fd %d", errno);
+        return -1;
+    }
+    return av_fd;
+}
+
+uint8_t* Filter::getIonBuffer(int fd, int size) {
+    uint8_t* avBuf = static_cast<uint8_t*>(
+            mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 /*offset*/));
+    if (avBuf == MAP_FAILED) {
+        ALOGE("[Filter] fail to allocate buffer %d", errno);
+        return NULL;
+    }
+    return avBuf;
+}
+
+native_handle_t* Filter::createNativeHandle(int fd) {
+    native_handle_t* nativeHandle;
+    if (fd < 0) {
+        nativeHandle = native_handle_create(/*numFd*/ 0, 0);
+    } else {
+        // Create a native handle to pass the av fd via the callback event.
+        nativeHandle = native_handle_create(/*numFd*/ 1, 0);
+    }
+    if (nativeHandle == NULL) {
+        ALOGE("[Filter] Failed to create native_handle %d", errno);
+        return NULL;
+    }
+    if (nativeHandle->numFds > 0) {
+        nativeHandle->data[0] = dup(fd);
+    }
+    return nativeHandle;
+}
+
+::ndk::ScopedAStatus Filter::createIndependentMediaEvents(vector<int8_t>& output) {
+    int av_fd = createAvIonFd(output.size());
+    if (av_fd == -1) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::UNKNOWN_ERROR));
+    }
+    // copy the filtered data to the buffer
+    uint8_t* avBuffer = getIonBuffer(av_fd, output.size());
+    if (avBuffer == NULL) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::UNKNOWN_ERROR));
+    }
+    memcpy(avBuffer, output.data(), output.size() * sizeof(uint8_t));
+
+    native_handle_t* nativeHandle = createNativeHandle(av_fd);
+    if (nativeHandle == NULL) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::UNKNOWN_ERROR));
+    }
+
+    // Create a dataId and add a <dataId, av_fd> pair into the dataId2Avfd map
+    uint64_t dataId = mLastUsedDataId++ /*createdUID*/;
+    mDataId2Avfd[dataId] = dup(av_fd);
+
+    // Create mediaEvent and send callback
+    auto event = DemuxFilterEvent::make<DemuxFilterEvent::Tag::media>();
+    auto& mediaEvent = event.get<DemuxFilterEvent::Tag::media>();
+    mediaEvent.avMemory = ::android::dupToAidl(nativeHandle);
+    mediaEvent.dataLength = static_cast<int64_t>(output.size());
+    mediaEvent.avDataId = static_cast<int64_t>(dataId);
+    if (mPts) {
+        mediaEvent.pts = mPts;
+        mPts = 0;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mFilterEventsLock);
+        mFilterEvents.push_back(std::move(event));
+    }
+
+    // Clear and log
+    native_handle_close(nativeHandle);
+    native_handle_delete(nativeHandle);
+    output.clear();
+    mAvBufferCopyCount = 0;
+    if (DEBUG_FILTER) {
+        ALOGD("[Filter] av data length %d", static_cast<int32_t>(output.size()));
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Filter::createShareMemMediaEvents(vector<int8_t>& output) {
+    // copy the filtered data to the shared buffer
+    uint8_t* sharedAvBuffer =
+            getIonBuffer(mSharedAvMemHandle->data[0], output.size() + mSharedAvMemOffset);
+    if (sharedAvBuffer == NULL) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::UNKNOWN_ERROR));
+    }
+    memcpy(sharedAvBuffer + mSharedAvMemOffset, output.data(), output.size() * sizeof(uint8_t));
+
+    // Create a memory handle with numFds == 0
+    native_handle_t* nativeHandle = createNativeHandle(-1);
+    if (nativeHandle == NULL) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::UNKNOWN_ERROR));
+    }
+
+    // Create mediaEvent and send callback
+    auto event = DemuxFilterEvent::make<DemuxFilterEvent::Tag::media>();
+    auto& mediaEvent = event.get<DemuxFilterEvent::Tag::media>();
+    mediaEvent.avMemory = ::android::dupToAidl(nativeHandle);
+    mediaEvent.offset = mSharedAvMemOffset;
+    mediaEvent.dataLength = static_cast<int64_t>(output.size());
+    if (mPts) {
+        mediaEvent.pts = mPts;
+        mPts = 0;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mFilterEventsLock);
+        mFilterEvents.push_back(std::move(event));
+    }
+
+    mSharedAvMemOffset += output.size();
+
+    // Clear and log
+    native_handle_close(nativeHandle);
+    native_handle_delete(nativeHandle);
+    output.clear();
+    if (DEBUG_FILTER) {
+        ALOGD("[Filter] shared av data length %d", static_cast<int32_t>(output.size()));
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+bool Filter::sameFile(int fd1, int fd2) {
+    struct stat stat1, stat2;
+    if (fstat(fd1, &stat1) < 0 || fstat(fd2, &stat2) < 0) {
+        return false;
+    }
+    return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino);
+}
+
+void Filter::createMediaEvent(vector<DemuxFilterEvent>& events) {
+    AudioExtraMetaData audio;
+    audio.adFade = 1;
+    audio.adPan = 2;
+    audio.versionTextTag = 3;
+    audio.adGainCenter = 4;
+    audio.adGainFront = 5;
+    audio.adGainSurround = 6;
+
+    DemuxFilterMediaEvent mediaEvent;
+    mediaEvent.streamId = 1;
+    mediaEvent.isPtsPresent = true;
+    mediaEvent.isDtsPresent = false;
+    mediaEvent.dataLength = 3;
+    mediaEvent.offset = 4;
+    mediaEvent.isSecureMemory = true;
+    mediaEvent.mpuSequenceNumber = 6;
+    mediaEvent.isPesPrivateData = true;
+    mediaEvent.extraMetaData.set<DemuxFilterMediaEventExtraMetaData::Tag::audio>(audio);
+
+    int av_fd = createAvIonFd(BUFFER_SIZE_16M);
+    if (av_fd == -1) {
+        return;
+    }
+
+    native_handle_t* nativeHandle = createNativeHandle(av_fd);
+    if (nativeHandle == nullptr) {
+        ::close(av_fd);
+        ALOGE("[Filter] Failed to create native_handle %d", errno);
+        return;
+    }
+
+    // Create a dataId and add a <dataId, av_fd> pair into the dataId2Avfd map
+    uint64_t dataId = mLastUsedDataId++ /*createdUID*/;
+    mDataId2Avfd[dataId] = dup(av_fd);
+
+    mediaEvent.avDataId = static_cast<int64_t>(dataId);
+    mediaEvent.avMemory = ::android::dupToAidl(nativeHandle);
+
+    events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::media>(std::move(mediaEvent)));
+
+    native_handle_close(nativeHandle);
+    native_handle_delete(nativeHandle);
+}
+
+void Filter::createTsRecordEvent(vector<DemuxFilterEvent>& events) {
+    DemuxPid pid;
+    DemuxFilterScIndexMask mask;
+    DemuxFilterTsRecordEvent tsRecord1;
+    pid.set<DemuxPid::Tag::tPid>(1);
+    mask.set<DemuxFilterScIndexMask::Tag::scIndex>(1);
+    tsRecord1.pid = pid;
+    tsRecord1.tsIndexMask = 1;
+    tsRecord1.scIndexMask = mask;
+    tsRecord1.byteNumber = 2;
+
+    DemuxFilterTsRecordEvent tsRecord2;
+    tsRecord2.pts = 1;
+    tsRecord2.firstMbInSlice = 2;  // random address
+
+    events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::tsRecord>(std::move(tsRecord1)));
+    events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::tsRecord>(std::move(tsRecord2)));
+}
+
+void Filter::createMmtpRecordEvent(vector<DemuxFilterEvent>& events) {
+    DemuxFilterMmtpRecordEvent mmtpRecord1;
+    mmtpRecord1.scHevcIndexMask = 1;
+    mmtpRecord1.byteNumber = 2;
+
+    DemuxFilterMmtpRecordEvent mmtpRecord2;
+    mmtpRecord2.pts = 1;
+    mmtpRecord2.mpuSequenceNumber = 2;
+    mmtpRecord2.firstMbInSlice = 3;
+    mmtpRecord2.tsIndexMask = 4;
+
+    events.push_back(
+            DemuxFilterEvent::make<DemuxFilterEvent::Tag::mmtpRecord>(std::move(mmtpRecord1)));
+    events.push_back(
+            DemuxFilterEvent::make<DemuxFilterEvent::Tag::mmtpRecord>(std::move(mmtpRecord2)));
+}
+
+void Filter::createSectionEvent(vector<DemuxFilterEvent>& events) {
+    DemuxFilterSectionEvent section;
+    section.tableId = 1;
+    section.version = 2;
+    section.sectionNum = 3;
+    section.dataLength = 0;
+
+    events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::section>(std::move(section)));
+}
+
+void Filter::createPesEvent(vector<DemuxFilterEvent>& events) {
+    DemuxFilterPesEvent pes;
+    pes.streamId = 1;
+    pes.dataLength = 1;
+    pes.mpuSequenceNumber = 2;
+
+    events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::pes>(std::move(pes)));
+}
+
+void Filter::createDownloadEvent(vector<DemuxFilterEvent>& events) {
+    DemuxFilterDownloadEvent download;
+    download.itemId = 1;
+    download.downloadId = 1;
+    download.mpuSequenceNumber = 2;
+    download.itemFragmentIndex = 3;
+    download.lastItemFragmentIndex = 4;
+    download.dataLength = 0;
+
+    events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::download>(std::move(download)));
+}
+
+void Filter::createIpPayloadEvent(vector<DemuxFilterEvent>& events) {
+    DemuxFilterIpPayloadEvent ipPayload;
+    ipPayload.dataLength = 0;
+
+    events.push_back(
+            DemuxFilterEvent::make<DemuxFilterEvent::Tag::ipPayload>(std::move(ipPayload)));
+}
+
+void Filter::createTemiEvent(vector<DemuxFilterEvent>& events) {
+    DemuxFilterTemiEvent temi;
+    temi.pts = 1;
+    temi.descrTag = 2;
+    temi.descrData = {3};
+
+    events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::temi>(std::move(temi)));
+}
+
+void Filter::createMonitorEvent(vector<DemuxFilterEvent>& events) {
+    DemuxFilterMonitorEvent monitor;
+    monitor.set<DemuxFilterMonitorEvent::Tag::scramblingStatus>(ScramblingStatus::SCRAMBLED);
+
+    events.push_back(
+            DemuxFilterEvent::make<DemuxFilterEvent::Tag::monitorEvent>(std::move(monitor)));
+}
+
+void Filter::createRestartEvent(vector<DemuxFilterEvent>& events) {
+    events.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::startId>(1));
+}
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Filter.h b/tv/tuner/aidl/default/Filter.h
new file mode 100644
index 0000000..e301249
--- /dev/null
+++ b/tv/tuner/aidl/default/Filter.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/BnFilter.h>
+#include <aidl/android/hardware/tv/tuner/Constant.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterStatus.h>
+
+#include <fmq/AidlMessageQueue.h>
+#include <inttypes.h>
+#include <ion/ion.h>
+#include <math.h>
+#include <sys/stat.h>
+#include <atomic>
+#include <condition_variable>
+#include <set>
+#include <thread>
+
+#include "Demux.h"
+#include "Dvr.h"
+#include "Frontend.h"
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+using ::aidl::android::hardware::common::NativeHandle;
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::hardware::EventFlag;
+
+using FilterMQ = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+const uint32_t BUFFER_SIZE_16M = 0x1000000;
+
+class Demux;
+class Dvr;
+
+class FilterCallbackScheduler final {
+  public:
+    FilterCallbackScheduler(const std::shared_ptr<IFilterCallback>& cb);
+    ~FilterCallbackScheduler();
+
+    void onFilterEvent(DemuxFilterEvent&& event);
+    void onFilterStatus(const DemuxFilterStatus& status);
+
+    void setTimeDelayHint(int timeDelay);
+    void setDataSizeDelayHint(int dataSizeDelay);
+
+    bool hasCallbackRegistered() const;
+
+    void flushEvents();
+
+  private:
+    void start();
+    void stop();
+
+    void threadLoop();
+    void threadLoopOnce();
+
+    // function needs to be called while holding mLock
+    bool isDataSizeDelayConditionMetLocked();
+
+    static int getDemuxFilterEventDataLength(const DemuxFilterEvent& event);
+
+  private:
+    std::shared_ptr<IFilterCallback> mCallback;
+    std::thread mCallbackThread;
+    std::atomic<bool> mIsRunning;
+
+    // mLock protects mCallbackBuffer, mIsConditionMet, mCv, mDataLength,
+    // mTimeDelayInMs, and mDataSizeDelayInBytes
+    std::mutex mLock;
+    std::vector<DemuxFilterEvent> mCallbackBuffer;
+    bool mIsConditionMet;
+    std::condition_variable mCv;
+    int mDataLength;
+    int mTimeDelayInMs;
+    int mDataSizeDelayInBytes;
+};
+
+class Filter : public BnFilter {
+    friend class FilterCallbackScheduler;
+
+  public:
+    Filter(DemuxFilterType type, int64_t filterId, uint32_t bufferSize,
+           const std::shared_ptr<IFilterCallback>& cb, std::shared_ptr<Demux> demux);
+
+    ~Filter();
+
+    ::ndk::ScopedAStatus getQueueDesc(
+            MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue) override;
+    ::ndk::ScopedAStatus close() override;
+    ::ndk::ScopedAStatus configure(const DemuxFilterSettings& in_settings) override;
+    ::ndk::ScopedAStatus configureAvStreamType(const AvStreamType& in_avStreamType) override;
+    ::ndk::ScopedAStatus configureIpCid(int32_t in_ipCid) override;
+    ::ndk::ScopedAStatus configureMonitorEvent(int32_t in_monitorEventTypes) override;
+    ::ndk::ScopedAStatus start() override;
+    ::ndk::ScopedAStatus stop() override;
+    ::ndk::ScopedAStatus flush() override;
+    ::ndk::ScopedAStatus getAvSharedHandle(NativeHandle* out_avMemory,
+                                           int64_t* _aidl_return) override;
+    ::ndk::ScopedAStatus getId(int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus getId64Bit(int64_t* _aidl_return) override;
+    ::ndk::ScopedAStatus releaseAvHandle(const NativeHandle& in_avMemory,
+                                         int64_t in_avDataId) override;
+    ::ndk::ScopedAStatus setDataSource(const std::shared_ptr<IFilter>& in_filter) override;
+    ::ndk::ScopedAStatus setDelayHint(const FilterDelayHint& in_hint) override;
+
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
+    /**
+     * To create a FilterMQ and its Event Flag.
+     *
+     * Return false is any of the above processes fails.
+     */
+    bool createFilterMQ();
+    uint16_t getTpid();
+    void updateFilterOutput(vector<int8_t>& data);
+    void updateRecordOutput(vector<int8_t>& data);
+    void updatePts(uint64_t pts);
+    ::ndk::ScopedAStatus startFilterHandler();
+    ::ndk::ScopedAStatus startRecordFilterHandler();
+    void attachFilterToRecord(const std::shared_ptr<Dvr> dvr);
+    void detachFilterFromRecord();
+    void freeSharedAvHandle();
+    bool isMediaFilter() { return mIsMediaFilter; };
+    bool isPcrFilter() { return mIsPcrFilter; };
+    bool isRecordFilter() { return mIsRecordFilter; };
+
+  private:
+    // Demux service
+    std::shared_ptr<Demux> mDemux;
+    // Dvr reference once the filter is attached to any
+    std::shared_ptr<Dvr> mDvr = nullptr;
+
+    FilterCallbackScheduler mCallbackScheduler;
+
+    int64_t mFilterId;
+    int32_t mCid = static_cast<int32_t>(Constant::INVALID_IP_FILTER_CONTEXT_ID);
+    uint32_t mBufferSize;
+    DemuxFilterType mType;
+    bool mIsMediaFilter = false;
+    bool mIsPcrFilter = false;
+    bool mIsRecordFilter = false;
+    DemuxFilterSettings mFilterSettings;
+
+    uint16_t mTpid;
+    std::shared_ptr<IFilter> mDataSource;
+    bool mIsDataSourceDemux = true;
+    vector<int8_t> mFilterOutput;
+    vector<int8_t> mRecordFilterOutput;
+    int64_t mPts = 0;
+    unique_ptr<FilterMQ> mFilterMQ;
+    bool mIsUsingFMQ = false;
+    EventFlag* mFilterEventsFlag;
+    vector<DemuxFilterEvent> mFilterEvents;
+
+    // Thread handlers
+    std::thread mFilterThread;
+
+    // FMQ status local records
+    DemuxFilterStatus mFilterStatus;
+    /**
+     * If a specific filter's writing loop is still running
+     */
+    std::atomic<bool> mFilterThreadRunning;
+
+    /**
+     * How many times a filter should write
+     * TODO make this dynamic/random/can take as a parameter
+     */
+    const uint16_t SECTION_WRITE_COUNT = 10;
+
+    bool DEBUG_FILTER = false;
+
+    /**
+     * Filter handlers to handle the data filtering.
+     * They are also responsible to write the filtered output into the filter FMQ
+     * and update the filterEvent bound with the same filterId.
+     */
+    ::ndk::ScopedAStatus startSectionFilterHandler();
+    ::ndk::ScopedAStatus startPesFilterHandler();
+    ::ndk::ScopedAStatus startTsFilterHandler();
+    ::ndk::ScopedAStatus startMediaFilterHandler();
+    ::ndk::ScopedAStatus startPcrFilterHandler();
+    ::ndk::ScopedAStatus startTemiFilterHandler();
+    ::ndk::ScopedAStatus startFilterLoop();
+
+    void deleteEventFlag();
+    bool writeDataToFilterMQ(const std::vector<int8_t>& data);
+    bool readDataFromMQ();
+    bool writeSectionsAndCreateEvent(vector<int8_t>& data);
+    void maySendFilterStatusCallback();
+    DemuxFilterStatus checkFilterStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
+                                              uint32_t highThreshold, uint32_t lowThreshold);
+    /**
+     * A dispatcher to read and dispatch input data to all the started filters.
+     * Each filter handler handles the data filtering/output writing/filterEvent updating.
+     */
+    bool startFilterDispatcher();
+    static void* __threadLoopFilter(void* user);
+    void filterThreadLoop();
+
+    int createAvIonFd(int size);
+    uint8_t* getIonBuffer(int fd, int size);
+    native_handle_t* createNativeHandle(int fd);
+    ::ndk::ScopedAStatus createMediaFilterEventWithIon(vector<int8_t>& output);
+    ::ndk::ScopedAStatus createIndependentMediaEvents(vector<int8_t>& output);
+    ::ndk::ScopedAStatus createShareMemMediaEvents(vector<int8_t>& output);
+    bool sameFile(int fd1, int fd2);
+
+    void createMediaEvent(vector<DemuxFilterEvent>&);
+    void createTsRecordEvent(vector<DemuxFilterEvent>&);
+    void createMmtpRecordEvent(vector<DemuxFilterEvent>&);
+    void createSectionEvent(vector<DemuxFilterEvent>&);
+    void createPesEvent(vector<DemuxFilterEvent>&);
+    void createDownloadEvent(vector<DemuxFilterEvent>&);
+    void createIpPayloadEvent(vector<DemuxFilterEvent>&);
+    void createTemiEvent(vector<DemuxFilterEvent>&);
+    void createMonitorEvent(vector<DemuxFilterEvent>&);
+    void createRestartEvent(vector<DemuxFilterEvent>&);
+
+    /**
+     * Lock to protect writes to the FMQs
+     */
+    std::mutex mWriteLock;
+    /**
+     * Lock to protect writes to the filter event
+     */
+    // TODO make each filter separate event lock
+    std::mutex mFilterEventsLock;
+    /**
+     * Lock to protect writes to the input status
+     */
+    std::mutex mFilterStatusLock;
+    std::mutex mFilterOutputLock;
+    std::mutex mRecordFilterOutputLock;
+
+    // temp handle single PES filter
+    // TODO handle mulptiple Pes filters
+    int mPesSizeLeft = 0;
+    vector<int8_t> mPesOutput;
+
+    // A map from data id to ion handle
+    std::map<uint64_t, int> mDataId2Avfd;
+    uint64_t mLastUsedDataId = 1;
+    int mAvBufferCopyCount = 0;
+
+    // Shared A/V memory handle
+    native_handle_t* mSharedAvMemHandle = nullptr;
+    bool mUsingSharedAvMem = false;
+    int64_t mSharedAvMemOffset = 0;
+
+    uint32_t mAudioStreamType;
+    uint32_t mVideoStreamType;
+
+    // Scrambling status to be monitored
+    uint32_t mStatuses = 0;
+
+    bool mConfigured = false;
+    int mStartId = 0;
+    uint8_t mScramblingStatusMonitored = 0;
+    uint8_t mIpCidMonitored = 0;
+};
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Frontend.cpp b/tv/tuner/aidl/default/Frontend.cpp
new file mode 100644
index 0000000..714612d
--- /dev/null
+++ b/tv/tuner/aidl/default/Frontend.cpp
@@ -0,0 +1,783 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "android.hardware.tv.tuner-service.example-Frontend"
+
+#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <utils/Log.h>
+
+#include "Frontend.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+Frontend::Frontend(FrontendType type, int32_t id, std::shared_ptr<Tuner> tuner) {
+    mType = type;
+    mId = id;
+    mTuner = tuner;
+    // Init callback to nullptr
+    mCallback = nullptr;
+}
+
+Frontend::~Frontend() {}
+
+::ndk::ScopedAStatus Frontend::close() {
+    ALOGV("%s", __FUNCTION__);
+    // Reset callback
+    mCallback = nullptr;
+    mIsLocked = false;
+    mTuner->removeFrontend(mId);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Frontend::setCallback(const std::shared_ptr<IFrontendCallback>& in_callback) {
+    ALOGV("%s", __FUNCTION__);
+    if (in_callback == nullptr) {
+        ALOGW("[   WARN   ] Set Frontend callback with nullptr");
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    mCallback = in_callback;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Frontend::tune(const FrontendSettings& /* in_settings */) {
+    ALOGV("%s", __FUNCTION__);
+    if (mCallback == nullptr) {
+        ALOGW("[   WARN   ] Frontend callback is not set when tune");
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_STATE));
+    }
+
+    mTuner->frontendStartTune(mId);
+    mCallback->onEvent(FrontendEventType::LOCKED);
+    mIsLocked = true;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Frontend::stopTune() {
+    ALOGV("%s", __FUNCTION__);
+
+    mTuner->frontendStopTune(mId);
+    mIsLocked = false;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Frontend::scan(const FrontendSettings& in_settings, FrontendScanType in_type) {
+    ALOGV("%s", __FUNCTION__);
+
+    // If it's in middle of scanning, stop it first.
+    if (mScanThread.joinable()) {
+        mScanThread.join();
+    }
+
+    mFrontendSettings = in_settings;
+    mFrontendScanType = in_type;
+    mScanThread = std::thread(&Frontend::scanThreadLoop, this);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+void Frontend::scanThreadLoop() {
+    if (mIsLocked) {
+        FrontendScanMessage msg;
+        msg.set<FrontendScanMessage::Tag::isEnd>(true);
+        mCallback->onScanMessage(FrontendScanMessageType::END, msg);
+        return;
+    }
+
+    int64_t frequency = 0;
+    switch (mFrontendSettings.getTag()) {
+        case FrontendSettings::Tag::analog:
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::analog>().frequency;
+            break;
+        case FrontendSettings::Tag::atsc:
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::atsc>().frequency;
+            break;
+        case FrontendSettings::Tag::atsc3:
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::atsc3>().frequency;
+            break;
+        case FrontendSettings::Tag::dvbs:
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbs>().frequency;
+            break;
+        case FrontendSettings::Tag::dvbc:
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbc>().frequency;
+            break;
+        case FrontendSettings::Tag::dvbt:
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbt>().frequency;
+            break;
+        case FrontendSettings::Tag::isdbs:
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbs>().frequency;
+            break;
+        case FrontendSettings::Tag::isdbs3:
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbs3>().frequency;
+            break;
+        case FrontendSettings::Tag::isdbt:
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbt>().frequency;
+            break;
+        default:
+            break;
+    }
+
+    if (mFrontendScanType == FrontendScanType::SCAN_BLIND) {
+        frequency += 100 * 1000;
+    }
+
+    {
+        FrontendScanMessage msg;
+        vector<int64_t> frequencies = {frequency};
+        msg.set<FrontendScanMessage::Tag::frequencies>(frequencies);
+        mCallback->onScanMessage(FrontendScanMessageType::FREQUENCY, msg);
+    }
+
+    {
+        FrontendScanMessage msg;
+        msg.set<FrontendScanMessage::Tag::progressPercent>(20);
+        mCallback->onScanMessage(FrontendScanMessageType::PROGRESS_PERCENT, msg);
+    }
+
+    {
+        FrontendScanMessage msg;
+        vector<int32_t> symbolRates = {30};
+        msg.set<FrontendScanMessage::Tag::symbolRates>(symbolRates);
+        mCallback->onScanMessage(FrontendScanMessageType::SYMBOL_RATE, msg);
+    }
+
+    if (mType == FrontendType::DVBT) {
+        FrontendScanMessage msg;
+        msg.set<FrontendScanMessage::Tag::hierarchy>(FrontendDvbtHierarchy::HIERARCHY_NON_NATIVE);
+        mCallback->onScanMessage(FrontendScanMessageType::HIERARCHY, msg);
+    }
+
+    if (mType == FrontendType::ANALOG) {
+        FrontendScanMessage msg;
+        msg.set<FrontendScanMessage::Tag::analogType>(FrontendAnalogType::PAL);
+        mCallback->onScanMessage(FrontendScanMessageType::ANALOG_TYPE, msg);
+    }
+
+    {
+        FrontendScanMessage msg;
+        vector<int32_t> plpIds = {2};
+        msg.set<FrontendScanMessage::Tag::plpIds>(plpIds);
+        mCallback->onScanMessage(FrontendScanMessageType::PLP_IDS, msg);
+    }
+
+    {
+        FrontendScanMessage msg;
+        vector<int32_t> groupIds = {3};
+        msg.set<FrontendScanMessage::Tag::groupIds>(groupIds);
+        mCallback->onScanMessage(FrontendScanMessageType::GROUP_IDS, msg);
+    }
+
+    {
+        FrontendScanMessage msg;
+        vector<int32_t> inputStreamIds = {1};
+        msg.set<FrontendScanMessage::Tag::inputStreamIds>(inputStreamIds);
+        mCallback->onScanMessage(FrontendScanMessageType::INPUT_STREAM_IDS, msg);
+    }
+
+    switch (mType) {
+        case FrontendType::DVBT: {
+            FrontendScanMessage msg;
+            FrontendScanMessageStandard std;
+            std.set<FrontendScanMessageStandard::Tag::tStd>(FrontendDvbtStandard::AUTO);
+            msg.set<FrontendScanMessage::Tag::std>(std);
+            mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg);
+            break;
+        }
+        case FrontendType::DVBS: {
+            FrontendScanMessage msg;
+            FrontendScanMessageStandard std;
+            std.set<FrontendScanMessageStandard::Tag::sStd>(FrontendDvbsStandard::AUTO);
+            msg.set<FrontendScanMessage::Tag::std>(std);
+            mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg);
+            break;
+        }
+        case FrontendType::ANALOG: {
+            FrontendScanMessage msg;
+            FrontendScanMessageStandard std;
+            std.set<FrontendScanMessageStandard::Tag::sifStd>(FrontendAnalogSifStandard::AUTO);
+            msg.set<FrontendScanMessage::Tag::std>(std);
+            mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg);
+            break;
+        }
+        default:
+            break;
+    }
+
+    {
+        FrontendScanMessage msg;
+        FrontendScanAtsc3PlpInfo info;
+        info.plpId = 1;
+        info.bLlsFlag = false;
+        vector<FrontendScanAtsc3PlpInfo> atsc3PlpInfos = {info};
+        msg.set<FrontendScanMessage::Tag::atsc3PlpInfos>(atsc3PlpInfos);
+        mCallback->onScanMessage(FrontendScanMessageType::ATSC3_PLP_INFO, msg);
+    }
+
+    {
+        FrontendScanMessage msg;
+        FrontendModulation modulation;
+        modulation.set<FrontendModulation::Tag::dvbc>(FrontendDvbcModulation::MOD_16QAM);
+        msg.set<FrontendScanMessage::Tag::modulation>(modulation);
+        mCallback->onScanMessage(FrontendScanMessageType::MODULATION, msg);
+    }
+
+    {
+        FrontendScanMessage msg;
+        msg.set<FrontendScanMessage::Tag::isHighPriority>(true);
+        mCallback->onScanMessage(FrontendScanMessageType::HIGH_PRIORITY, msg);
+    }
+
+    if (mType == FrontendType::DVBT) {
+        FrontendScanMessage msg;
+        vector<int32_t> dvbtCellIds = {0, 1};
+        msg.set<FrontendScanMessage::Tag::dvbtCellIds>(dvbtCellIds);
+        mCallback->onScanMessage(FrontendScanMessageType::DVBT_CELL_IDS, msg);
+    }
+
+    {
+        FrontendScanMessage msg;
+        msg.set<FrontendScanMessage::Tag::isLocked>(true);
+        mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
+        mIsLocked = true;
+    }
+}
+
+::ndk::ScopedAStatus Frontend::stopScan() {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mScanThread.joinable()) {
+        mScanThread.join();
+    }
+
+    mIsLocked = false;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Frontend::getStatus(const std::vector<FrontendStatusType>& in_statusTypes,
+                                         std::vector<FrontendStatus>* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    for (int i = 0; i < in_statusTypes.size(); i++) {
+        FrontendStatusType type = in_statusTypes[i];
+        FrontendStatus status;
+        // assign randomly selected values for testing.
+        switch (type) {
+            case FrontendStatusType::DEMOD_LOCK: {
+                status.set<FrontendStatus::isDemodLocked>(true);
+                break;
+            }
+            case FrontendStatusType::SNR: {
+                status.set<FrontendStatus::snr>(221);
+                break;
+            }
+            case FrontendStatusType::BER: {
+                status.set<FrontendStatus::ber>(1);
+                break;
+            }
+            case FrontendStatusType::PER: {
+                status.set<FrontendStatus::per>(2);
+                break;
+            }
+            case FrontendStatusType::PRE_BER: {
+                status.set<FrontendStatus::preBer>(3);
+                break;
+            }
+            case FrontendStatusType::SIGNAL_QUALITY: {
+                status.set<FrontendStatus::signalQuality>(4);
+                break;
+            }
+            case FrontendStatusType::SIGNAL_STRENGTH: {
+                status.set<FrontendStatus::signalStrength>(5);
+                break;
+            }
+            case FrontendStatusType::SYMBOL_RATE: {
+                status.set<FrontendStatus::symbolRate>(6);
+                break;
+            }
+            case FrontendStatusType::FEC: {
+                status.set<FrontendStatus::innerFec>(FrontendInnerFec::FEC_2_9);  // value = 1 << 7
+                break;
+            }
+            case FrontendStatusType::MODULATION: {
+                switch (mType) {
+                    case FrontendType::ISDBS: {
+                        FrontendModulationStatus modulationStatus;
+                        modulationStatus.set<FrontendModulationStatus::Tag::isdbs>(
+                                FrontendIsdbsModulation::MOD_BPSK);  // value = 1 << 1
+                        status.set<FrontendStatus::modulationStatus>(modulationStatus);
+                        break;
+                    }
+                    case FrontendType::DVBC: {
+                        FrontendModulationStatus modulationStatus;
+                        modulationStatus.set<FrontendModulationStatus::Tag::dvbc>(
+                                FrontendDvbcModulation::MOD_16QAM);  // value = 1 << 1
+                        status.set<FrontendStatus::modulationStatus>(modulationStatus);
+                        break;
+                    }
+                    case FrontendType::DVBS: {
+                        FrontendModulationStatus modulationStatus;
+                        modulationStatus.set<FrontendModulationStatus::Tag::dvbs>(
+                                FrontendDvbsModulation::MOD_QPSK);  // value = 1 << 1
+                        status.set<FrontendStatus::modulationStatus>(modulationStatus);
+                        break;
+                    }
+                    case FrontendType::ISDBS3: {
+                        FrontendModulationStatus modulationStatus;
+                        modulationStatus.set<FrontendModulationStatus::Tag::isdbs3>(
+                                FrontendIsdbs3Modulation::MOD_BPSK);  // value = 1 << 1
+                        status.set<FrontendStatus::modulationStatus>(modulationStatus);
+                        break;
+                    }
+                    case FrontendType::ISDBT: {
+                        FrontendModulationStatus modulationStatus;
+                        modulationStatus.set<FrontendModulationStatus::Tag::isdbt>(
+                                FrontendIsdbtModulation::MOD_DQPSK);  // value = 1 << 1
+                        status.set<FrontendStatus::modulationStatus>(modulationStatus);
+                        break;
+                    }
+                    default:
+                        break;
+                }
+                break;
+            }
+            case FrontendStatusType::SPECTRAL: {
+                status.set<FrontendStatus::inversion>(FrontendSpectralInversion::NORMAL);
+                break;
+            }
+            case FrontendStatusType::LNB_VOLTAGE: {
+                status.set<FrontendStatus::lnbVoltage>(LnbVoltage::VOLTAGE_5V);
+                break;
+            }
+            case FrontendStatusType::PLP_ID: {
+                status.set<FrontendStatus::plpId>(101);
+                break;
+            }
+            case FrontendStatusType::EWBS: {
+                status.set<FrontendStatus::isEWBS>(false);
+                break;
+            }
+            case FrontendStatusType::AGC: {
+                status.set<FrontendStatus::agc>(7);
+                break;
+            }
+            case FrontendStatusType::LNA: {
+                status.set<FrontendStatus::isLnaOn>(false);
+                break;
+            }
+            case FrontendStatusType::LAYER_ERROR: {
+                vector<bool> v = {false, true, true};
+                status.set<FrontendStatus::isLayerError>(v);
+                break;
+            }
+            case FrontendStatusType::MER: {
+                status.set<FrontendStatus::mer>(8);
+                break;
+            }
+            case FrontendStatusType::FREQ_OFFSET: {
+                status.set<FrontendStatus::freqOffset>(9);
+                break;
+            }
+            case FrontendStatusType::HIERARCHY: {
+                status.set<FrontendStatus::hierarchy>(FrontendDvbtHierarchy::HIERARCHY_1_NATIVE);
+                break;
+            }
+            case FrontendStatusType::RF_LOCK: {
+                status.set<FrontendStatus::isRfLocked>(false);
+                break;
+            }
+            case FrontendStatusType::ATSC3_PLP_INFO: {
+                FrontendStatusAtsc3PlpInfo info1;
+                info1.plpId = 3;
+                info1.isLocked = false;
+                info1.uec = 313;
+                FrontendStatusAtsc3PlpInfo info2;
+                info2.plpId = 5;
+                info2.isLocked = true;
+                info2.uec = 515;
+                vector<FrontendStatusAtsc3PlpInfo> infos = {info1, info2};
+                status.set<FrontendStatus::plpInfo>(infos);
+                break;
+            }
+            case FrontendStatusType::MODULATIONS: {
+                FrontendModulation modulation;
+                vector<FrontendModulation> modulations;
+                switch (mType) {
+                    case FrontendType::ISDBS: {
+                        modulation.set<FrontendModulation::Tag::isdbs>(
+                                FrontendIsdbsModulation::MOD_BPSK);  // value = 1 << 1
+                        modulations.push_back(modulation);
+                        status.set<FrontendStatus::modulations>(modulations);
+                        break;
+                    }
+                    case FrontendType::DVBC: {
+                        modulation.set<FrontendModulation::Tag::dvbc>(
+                                FrontendDvbcModulation::MOD_16QAM);  // value = 1 << 1
+                        modulations.push_back(modulation);
+                        status.set<FrontendStatus::modulations>(modulations);
+                        break;
+                    }
+                    case FrontendType::DVBS: {
+                        modulation.set<FrontendModulation::Tag::dvbs>(
+                                FrontendDvbsModulation::MOD_QPSK);  // value = 1 << 1
+                        modulations.push_back(modulation);
+                        status.set<FrontendStatus::modulations>(modulations);
+                        break;
+                    }
+                    case FrontendType::DVBT: {
+                        modulation.set<FrontendModulation::Tag::dvbt>(
+                                FrontendDvbtConstellation::CONSTELLATION_16QAM_R);  // value = 1 <<
+                                                                                    // 16
+                        modulations.push_back(modulation);
+                        status.set<FrontendStatus::modulations>(modulations);
+                        break;
+                    }
+                    case FrontendType::ISDBS3: {
+                        modulation.set<FrontendModulation::Tag::isdbs3>(
+                                FrontendIsdbs3Modulation::MOD_BPSK);  //  value = 1 << 1
+                        modulations.push_back(modulation);
+                        status.set<FrontendStatus::modulations>(modulations);
+                        break;
+                    }
+                    case FrontendType::ISDBT: {
+                        modulation.set<FrontendModulation::Tag::isdbt>(
+                                FrontendIsdbtModulation::MOD_DQPSK);  // value = 1 << 1
+                        modulations.push_back(modulation);
+                        status.set<FrontendStatus::modulations>(modulations);
+                        break;
+                    }
+                    case FrontendType::ATSC: {
+                        modulation.set<FrontendModulation::Tag::atsc>(
+                                FrontendAtscModulation::MOD_8VSB);  // value = 1 << 2
+                        modulations.push_back(modulation);
+                        status.set<FrontendStatus::modulations>(modulations);
+                        break;
+                    }
+                    case FrontendType::ATSC3: {
+                        modulation.set<FrontendModulation::Tag::atsc3>(
+                                FrontendAtsc3Modulation::MOD_QPSK);  // value = 1 << 1
+                        modulations.push_back(modulation);
+                        status.set<FrontendStatus::modulations>(modulations);
+                        break;
+                    }
+                    case FrontendType::DTMB: {
+                        modulation.set<FrontendModulation::Tag::dtmb>(
+                                FrontendDtmbModulation::CONSTELLATION_4QAM);  // value = 1 << 1
+                        modulations.push_back(modulation);
+                        status.set<FrontendStatus::modulations>(modulations);
+                        break;
+                    }
+                    default:
+                        break;
+                }
+                break;
+            }
+            case FrontendStatusType::BERS: {
+                vector<int32_t> bers = {1};
+                status.set<FrontendStatus::bers>(bers);
+                break;
+            }
+            case FrontendStatusType::CODERATES: {
+                vector<FrontendInnerFec> rates;
+                rates.push_back(FrontendInnerFec::FEC_6_15);  // value = 1 << 39
+                status.set<FrontendStatus::codeRates>(rates);
+                break;
+            }
+            case FrontendStatusType::BANDWIDTH: {
+                FrontendBandwidth bandwidth;
+                switch (mType) {
+                    case FrontendType::DVBC: {
+                        bandwidth.set<FrontendBandwidth::Tag::dvbc>(
+                                FrontendDvbcBandwidth::BANDWIDTH_6MHZ);  // value = 1 << 1
+                        status.set<FrontendStatus::bandwidth>(bandwidth);
+                        break;
+                    }
+                    case FrontendType::DVBT: {
+                        bandwidth.set<FrontendBandwidth::Tag::dvbt>(
+                                FrontendDvbtBandwidth::BANDWIDTH_8MHZ);  // value = 1 << 1
+                        status.set<FrontendStatus::bandwidth>(bandwidth);
+                        break;
+                    }
+                    case FrontendType::ISDBT: {
+                        bandwidth.set<FrontendBandwidth::Tag::isdbt>(
+                                FrontendIsdbtBandwidth::BANDWIDTH_8MHZ);  // value = 1 << 1
+                        status.set<FrontendStatus::bandwidth>(bandwidth);
+                        break;
+                    }
+                    case FrontendType::ATSC3: {
+                        bandwidth.set<FrontendBandwidth::Tag::atsc3>(
+                                FrontendAtsc3Bandwidth::BANDWIDTH_6MHZ);  // value = 1 << 1
+                        status.set<FrontendStatus::bandwidth>(bandwidth);
+                        break;
+                    }
+                    case FrontendType::DTMB: {
+                        bandwidth.set<FrontendBandwidth::Tag::dtmb>(
+                                FrontendDtmbBandwidth::BANDWIDTH_8MHZ);  // value = 1 << 1
+                        status.set<FrontendStatus::bandwidth>(bandwidth);
+                        break;
+                    }
+                    default:
+                        break;
+                }
+                break;
+            }
+            case FrontendStatusType::GUARD_INTERVAL: {
+                FrontendGuardInterval interval;
+                switch (mType) {
+                    case FrontendType::DVBT: {
+                        interval.set<FrontendGuardInterval::Tag::dvbt>(
+                                FrontendDvbtGuardInterval::INTERVAL_1_32);  // value = 1 << 1
+                        status.set<FrontendStatus::interval>(interval);
+                        break;
+                    }
+                    case FrontendType::ISDBT: {
+                        interval.set<FrontendGuardInterval::Tag::isdbt>(
+                                FrontendIsdbtGuardInterval::INTERVAL_1_32);  // value = 1 << 1
+                        status.set<FrontendStatus::interval>(interval);
+                        break;
+                    }
+                    case FrontendType::DTMB: {
+                        interval.set<FrontendGuardInterval::Tag::dtmb>(
+                                FrontendDtmbGuardInterval::PN_420_VARIOUS);  // value = 1 << 1
+                        status.set<FrontendStatus::interval>(interval);
+                        break;
+                    }
+                    default:
+                        break;
+                }
+                break;
+            }
+            case FrontendStatusType::TRANSMISSION_MODE: {
+                FrontendTransmissionMode transMode;
+                switch (mType) {
+                    case FrontendType::DVBT: {
+                        transMode.set<FrontendTransmissionMode::Tag::dvbt>(
+                                FrontendDvbtTransmissionMode::MODE_16K_E);  // value = 1 << 8
+                        status.set<FrontendStatus::transmissionMode>(transMode);
+                        break;
+                    }
+                    case FrontendType::ISDBT: {
+                        transMode.set<FrontendTransmissionMode::Tag::isdbt>(
+                                FrontendIsdbtMode::MODE_1);  // value = 1 << 1
+                        status.set<FrontendStatus::transmissionMode>(transMode);
+                        break;
+                    }
+                    case FrontendType::DTMB: {
+                        transMode.set<FrontendTransmissionMode::Tag::dtmb>(
+                                FrontendDtmbTransmissionMode::C1);  // value = 1 << 1
+                        status.set<FrontendStatus::transmissionMode>(transMode);
+                        break;
+                    }
+                    default:
+                        break;
+                }
+                break;
+            }
+            case FrontendStatusType::UEC: {
+                status.set<FrontendStatus::uec>(4);
+                break;
+            }
+            case FrontendStatusType::T2_SYSTEM_ID: {
+                status.set<FrontendStatus::systemId>(5);
+                break;
+            }
+            case FrontendStatusType::INTERLEAVINGS: {
+                FrontendInterleaveMode interleave;
+                vector<FrontendInterleaveMode> interleaves;
+                switch (mType) {
+                    case FrontendType::DVBC: {
+                        // value = 1 << 1
+                        interleave.set<FrontendInterleaveMode::Tag::dvbc>(
+                                FrontendCableTimeInterleaveMode::INTERLEAVING_128_1_0);
+                        interleaves.push_back(interleave);
+                        status.set<FrontendStatus::interleaving>(interleaves);
+                        break;
+                    }
+                    case FrontendType::ATSC3: {
+                        interleave.set<FrontendInterleaveMode::Tag::atsc3>(
+                                FrontendAtsc3TimeInterleaveMode::CTI);  // value = 1 << 1
+                        interleaves.push_back(interleave);
+                        status.set<FrontendStatus::interleaving>(interleaves);
+                        break;
+                    }
+                    case FrontendType::DTMB: {
+                        interleave.set<FrontendInterleaveMode::Tag::dtmb>(
+                                FrontendDtmbTimeInterleaveMode::TIMER_INT_240);  // value = 1 << 1
+                        interleaves.push_back(interleave);
+                        status.set<FrontendStatus::interleaving>(interleaves);
+                        break;
+                    }
+                    case FrontendType::ISDBT: {
+                        interleave.set<FrontendInterleaveMode::Tag::isdbt>(
+                                FrontendIsdbtTimeInterleaveMode::INTERLEAVE_1_0); // value = 1 << 1
+                        interleaves.push_back(interleave);
+                        status.set<FrontendStatus::interleaving>(interleaves);
+                        break;
+                    }
+                    default:
+                        break;
+                }
+                break;
+            }
+            case FrontendStatusType::ISDBT_SEGMENTS: {
+                vector<int32_t> segments = {2, 3};
+                status.set<FrontendStatus::isdbtSegment>(segments);
+                break;
+            }
+            case FrontendStatusType::TS_DATA_RATES: {
+                vector<int32_t> dataRates = {4, 5};
+                status.set<FrontendStatus::tsDataRate>(dataRates);
+                break;
+            }
+            case FrontendStatusType::ROLL_OFF: {
+                FrontendRollOff rollOff;
+                switch (mType) {
+                    case FrontendType::DVBS: {
+                        rollOff.set<FrontendRollOff::Tag::dvbs>(
+                                FrontendDvbsRolloff::ROLLOFF_0_35);  // value = 1
+                        status.set<FrontendStatus::rollOff>(rollOff);
+                        break;
+                    }
+                    case FrontendType::ISDBS: {
+                        rollOff.set<FrontendRollOff::Tag::isdbs>(
+                                FrontendIsdbsRolloff::ROLLOFF_0_35);  // value = 1
+                        status.set<FrontendStatus::rollOff>(rollOff);
+                        break;
+                    }
+                    case FrontendType::ISDBS3: {
+                        rollOff.set<FrontendRollOff::Tag::isdbs3>(
+                                FrontendIsdbs3Rolloff::ROLLOFF_0_03);  // value = 1
+                        status.set<FrontendStatus::rollOff>(rollOff);
+                        break;
+                    }
+                    default:
+                        break;
+                }
+                break;
+            }
+            case FrontendStatusType::IS_MISO: {
+                status.set<FrontendStatus::isMiso>(true);
+                break;
+            }
+            case FrontendStatusType::IS_LINEAR: {
+                status.set<FrontendStatus::isLinear>(true);
+                break;
+            }
+            case FrontendStatusType::IS_SHORT_FRAMES: {
+                status.set<FrontendStatus::isShortFrames>(true);
+                break;
+            }
+            case FrontendStatusType::ISDBT_MODE: {
+                status.set<FrontendStatus::isdbtMode>(FrontendIsdbtMode::AUTO);
+                break;
+            }
+            case FrontendStatusType::ISDBT_PARTIAL_RECEPTION_FLAG: {
+                status.set<FrontendStatus::partialReceptionFlag>(
+                        FrontendIsdbtPartialReceptionFlag::AUTO);
+                break;
+            }
+            case FrontendStatusType::STREAM_ID_LIST: {
+                vector<int32_t> streamIds = {0, 1};
+                status.set<FrontendStatus::streamIdList>(streamIds);
+                break;
+            }
+            case FrontendStatusType::DVBT_CELL_IDS: {
+                vector<int32_t> dvbtCellIds = {0, 1};
+                status.set<FrontendStatus::dvbtCellIds>(dvbtCellIds);
+                break;
+            }
+            default: {
+                continue;
+            }
+        }
+        _aidl_return->push_back(status);
+    }
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Frontend::setLnb(int32_t /* in_lnbId */) {
+    ALOGV("%s", __FUNCTION__);
+    if (!supportsSatellite()) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_STATE));
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Frontend::linkCiCam(int32_t in_ciCamId, int32_t* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    mCiCamId = in_ciCamId;
+    *_aidl_return = 0;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Frontend::unlinkCiCam(int32_t /* in_ciCamId */) {
+    ALOGV("%s", __FUNCTION__);
+
+    mCiCamId = -1;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+binder_status_t Frontend::dump(int fd, const char** /* args */, uint32_t /* numArgs */) {
+    dprintf(fd, "  Frontend %d\n", mId);
+    dprintf(fd, "    mType: %d\n", mType);
+    dprintf(fd, "    mIsLocked: %d\n", mIsLocked);
+    dprintf(fd, "    mCiCamId: %d\n", mCiCamId);
+    return STATUS_OK;
+}
+
+::ndk::ScopedAStatus Frontend::getHardwareInfo(std::string* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    *_aidl_return = "Sample Frontend";
+    return ::ndk::ScopedAStatus::ok();
+}
+
+FrontendType Frontend::getFrontendType() {
+    return mType;
+}
+
+int32_t Frontend::getFrontendId() {
+    return mId;
+}
+
+bool Frontend::supportsSatellite() {
+    return mType == FrontendType::DVBS || mType == FrontendType::ISDBS ||
+           mType == FrontendType::ISDBS3;
+}
+
+bool Frontend::isLocked() {
+    return mIsLocked;
+}
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Frontend.h b/tv/tuner/aidl/default/Frontend.h
new file mode 100644
index 0000000..fdedf1e
--- /dev/null
+++ b/tv/tuner/aidl/default/Frontend.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/BnFrontend.h>
+#include <fstream>
+#include <iostream>
+#include <thread>
+#include "Tuner.h"
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+class Tuner;
+
+class Frontend : public BnFrontend {
+  public:
+    Frontend(FrontendType type, int32_t id, std::shared_ptr<Tuner> tuner);
+
+    ::ndk::ScopedAStatus setCallback(
+            const std::shared_ptr<IFrontendCallback>& in_callback) override;
+    ::ndk::ScopedAStatus tune(const FrontendSettings& in_settings) override;
+    ::ndk::ScopedAStatus stopTune() override;
+    ::ndk::ScopedAStatus close() override;
+    ::ndk::ScopedAStatus scan(const FrontendSettings& in_settings,
+                              FrontendScanType in_type) override;
+    ::ndk::ScopedAStatus stopScan() override;
+    ::ndk::ScopedAStatus getStatus(const std::vector<FrontendStatusType>& in_statusTypes,
+                                   std::vector<FrontendStatus>* _aidl_return) override;
+    ::ndk::ScopedAStatus setLnb(int32_t in_lnbId) override;
+    ::ndk::ScopedAStatus linkCiCam(int32_t in_ciCamId, int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus unlinkCiCam(int32_t in_ciCamId) override;
+    ::ndk::ScopedAStatus getHardwareInfo(std::string* _aidl_return) override;
+
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
+    FrontendType getFrontendType();
+    int32_t getFrontendId();
+    string getSourceFile();
+    bool isLocked();
+
+  private:
+    virtual ~Frontend();
+    bool supportsSatellite();
+    void scanThreadLoop();
+
+    std::shared_ptr<IFrontendCallback> mCallback;
+    std::shared_ptr<Tuner> mTuner;
+    FrontendType mType = FrontendType::UNDEFINED;
+    int32_t mId = 0;
+    bool mIsLocked = false;
+    int32_t mCiCamId;
+    std::thread mScanThread;
+    FrontendSettings mFrontendSettings;
+    FrontendScanType mFrontendScanType;
+    std::ifstream mFrontendData;
+};
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Lnb.cpp b/tv/tuner/aidl/default/Lnb.cpp
new file mode 100644
index 0000000..35d2da6
--- /dev/null
+++ b/tv/tuner/aidl/default/Lnb.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "android.hardware.tv.tuner-service.example-Lnb"
+
+#include "Lnb.h"
+#include <utils/Log.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+Lnb::Lnb() {}
+
+Lnb::Lnb(int id) {
+    mId = id;
+}
+
+Lnb::~Lnb() {}
+
+::ndk::ScopedAStatus Lnb::setCallback(const std::shared_ptr<ILnbCallback>& /* in_callback */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Lnb::setVoltage(LnbVoltage /* in_voltage */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Lnb::setTone(LnbTone /* in_tone */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Lnb::setSatellitePosition(LnbPosition /* in_position */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Lnb::sendDiseqcMessage(const std::vector<uint8_t>& /* in_diseqcMessage */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Lnb::close() {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+int Lnb::getId() {
+    return mId;
+}
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Lnb.h b/tv/tuner/aidl/default/Lnb.h
new file mode 100644
index 0000000..bfe3097
--- /dev/null
+++ b/tv/tuner/aidl/default/Lnb.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/BnLnb.h>
+#include <aidl/android/hardware/tv/tuner/ITuner.h>
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+class Lnb : public BnLnb {
+  public:
+    Lnb();
+    Lnb(int id);
+
+    ::ndk::ScopedAStatus setCallback(const std::shared_ptr<ILnbCallback>& in_callback) override;
+    ::ndk::ScopedAStatus setVoltage(LnbVoltage in_voltage) override;
+    ::ndk::ScopedAStatus setTone(LnbTone in_tone) override;
+    ::ndk::ScopedAStatus setSatellitePosition(LnbPosition in_position) override;
+    ::ndk::ScopedAStatus sendDiseqcMessage(const std::vector<uint8_t>& in_diseqcMessage) override;
+    ::ndk::ScopedAStatus close() override;
+
+    int getId();
+
+  private:
+    int mId;
+    virtual ~Lnb();
+};
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/OWNERS b/tv/tuner/aidl/default/OWNERS
new file mode 100644
index 0000000..bf2b609
--- /dev/null
+++ b/tv/tuner/aidl/default/OWNERS
@@ -0,0 +1,3 @@
+hgchen@google.com
+shubang@google.com
+quxiangfang@google.com
diff --git a/tv/tuner/aidl/default/TimeFilter.cpp b/tv/tuner/aidl/default/TimeFilter.cpp
new file mode 100644
index 0000000..9611ed9
--- /dev/null
+++ b/tv/tuner/aidl/default/TimeFilter.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.tv.tuner-service.example-TimeFilter"
+
+#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <utils/Log.h>
+
+#include "TimeFilter.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+TimeFilter::TimeFilter() {}
+
+TimeFilter::TimeFilter(std::shared_ptr<Demux> demux) {
+    mDemux = demux;
+}
+
+TimeFilter::~TimeFilter() {}
+
+::ndk::ScopedAStatus TimeFilter::setTimeStamp(int64_t in_timeStamp) {
+    ALOGV("%s", __FUNCTION__);
+    if (in_timeStamp == INVALID_TIME_STAMP) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+    mTimeStamp = in_timeStamp;
+    mBeginTime = time(NULL);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TimeFilter::clearTimeStamp() {
+    ALOGV("%s", __FUNCTION__);
+    mTimeStamp = INVALID_TIME_STAMP;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TimeFilter::getTimeStamp(int64_t* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+    if (mTimeStamp == INVALID_TIME_STAMP) {
+        *_aidl_return = mTimeStamp;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    uint64_t currentTimeStamp = mTimeStamp + difftime(time(NULL), mBeginTime) * 900000;
+    *_aidl_return = currentTimeStamp;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TimeFilter::getSourceTime(int64_t* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    *_aidl_return = 0;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus TimeFilter::close() {
+    ALOGV("%s", __FUNCTION__);
+    mTimeStamp = INVALID_TIME_STAMP;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+binder_status_t TimeFilter::dump(int fd, const char** /* args */, uint32_t /* numArgs */) {
+    dprintf(fd, "    TimeFilter:\n");
+    dprintf(fd, "      mTimeStamp: %" PRIu64 "\n", mTimeStamp);
+    return STATUS_OK;
+}
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/TimeFilter.h b/tv/tuner/aidl/default/TimeFilter.h
new file mode 100644
index 0000000..5f4c2d4
--- /dev/null
+++ b/tv/tuner/aidl/default/TimeFilter.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/BnTimeFilter.h>
+#include "Demux.h"
+#include "time.h"
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+#define INVALID_TIME_STAMP -1
+
+class Demux;
+
+class TimeFilter : public BnTimeFilter {
+  public:
+    TimeFilter();
+    TimeFilter(std::shared_ptr<Demux> demux);
+    ~TimeFilter();
+
+    ::ndk::ScopedAStatus setTimeStamp(int64_t in_timeStamp) override;
+    ::ndk::ScopedAStatus clearTimeStamp() override;
+    ::ndk::ScopedAStatus getTimeStamp(int64_t* _aidl_return) override;
+    ::ndk::ScopedAStatus getSourceTime(int64_t* _aidl_return) override;
+    ::ndk::ScopedAStatus close() override;
+
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
+  private:
+    ::std::shared_ptr<Demux> mDemux;
+    uint64_t mTimeStamp = INVALID_TIME_STAMP;
+    time_t mBeginTime;
+};
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Tuner.cpp b/tv/tuner/aidl/default/Tuner.cpp
new file mode 100644
index 0000000..45f3dfa
--- /dev/null
+++ b/tv/tuner/aidl/default/Tuner.cpp
@@ -0,0 +1,402 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "android.hardware.tv.tuner-service.example-Tuner"
+
+#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <utils/Log.h>
+
+#include "Demux.h"
+#include "Descrambler.h"
+#include "Frontend.h"
+#include "Lnb.h"
+#include "Tuner.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+Tuner::Tuner() {}
+
+void Tuner::init() {
+    // Static Frontends array to maintain local frontends information
+    // Array index matches their FrontendId in the default impl
+    mFrontendSize = 10;
+    mFrontends[0] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBS, 0, this->ref<Tuner>());
+    mFrontends[1] = ndk::SharedRefBase::make<Frontend>(FrontendType::ATSC3, 1, this->ref<Tuner>());
+    mFrontends[2] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBC, 2, this->ref<Tuner>());
+    mFrontends[3] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBS, 3, this->ref<Tuner>());
+    mFrontends[4] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBT, 4, this->ref<Tuner>());
+    mFrontends[5] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBT, 5, this->ref<Tuner>());
+    mFrontends[6] = ndk::SharedRefBase::make<Frontend>(FrontendType::ANALOG, 6, this->ref<Tuner>());
+    mFrontends[7] = ndk::SharedRefBase::make<Frontend>(FrontendType::ATSC, 7, this->ref<Tuner>());
+    mFrontends[8] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBS3, 8, this->ref<Tuner>());
+    mFrontends[9] = ndk::SharedRefBase::make<Frontend>(FrontendType::DTMB, 9, this->ref<Tuner>());
+
+    vector<FrontendStatusType> statusCaps;
+
+    FrontendCapabilities capsIsdbs;
+    capsIsdbs.set<FrontendCapabilities::Tag::isdbsCaps>(FrontendIsdbsCapabilities());
+    mFrontendCaps[0] = capsIsdbs;
+    statusCaps = {
+            FrontendStatusType::DEMOD_LOCK,
+            FrontendStatusType::SNR,
+            FrontendStatusType::FEC,
+            FrontendStatusType::MODULATION,
+            FrontendStatusType::MODULATIONS,
+            FrontendStatusType::ROLL_OFF,
+            FrontendStatusType::STREAM_ID_LIST,
+    };
+    mFrontendStatusCaps[0] = statusCaps;
+
+    FrontendCapabilities capsAtsc3;
+    capsAtsc3.set<FrontendCapabilities::Tag::atsc3Caps>(FrontendAtsc3Capabilities());
+    mFrontendCaps[1] = capsAtsc3;
+    statusCaps = {
+            FrontendStatusType::BER,
+            FrontendStatusType::PER,
+            FrontendStatusType::ATSC3_PLP_INFO,
+            FrontendStatusType::MODULATIONS,
+            FrontendStatusType::BERS,
+            FrontendStatusType::INTERLEAVINGS,
+            FrontendStatusType::BANDWIDTH,
+    };
+    mFrontendStatusCaps[1] = statusCaps;
+
+    FrontendCapabilities capsDvbc;
+    capsDvbc.set<FrontendCapabilities::Tag::dvbcCaps>(FrontendDvbcCapabilities());
+    mFrontendCaps[2] = capsDvbc;
+    statusCaps = {
+            FrontendStatusType::PRE_BER,       FrontendStatusType::SIGNAL_QUALITY,
+            FrontendStatusType::MODULATION,    FrontendStatusType::SPECTRAL,
+            FrontendStatusType::MODULATIONS,   FrontendStatusType::CODERATES,
+            FrontendStatusType::INTERLEAVINGS, FrontendStatusType::BANDWIDTH,
+    };
+    mFrontendStatusCaps[2] = statusCaps;
+
+    FrontendCapabilities capsDvbs;
+    capsDvbs.set<FrontendCapabilities::Tag::dvbsCaps>(FrontendDvbsCapabilities());
+    mFrontendCaps[3] = capsDvbs;
+    statusCaps = {
+            FrontendStatusType::SIGNAL_STRENGTH, FrontendStatusType::SYMBOL_RATE,
+            FrontendStatusType::MODULATION,      FrontendStatusType::MODULATIONS,
+            FrontendStatusType::ROLL_OFF,        FrontendStatusType::IS_MISO,
+    };
+    mFrontendStatusCaps[3] = statusCaps;
+
+    FrontendCapabilities capsDvbt;
+    capsDvbt.set<FrontendCapabilities::Tag::dvbtCaps>(FrontendDvbtCapabilities());
+    mFrontendCaps[4] = capsDvbt;
+    statusCaps = {
+            FrontendStatusType::EWBS,
+            FrontendStatusType::PLP_ID,
+            FrontendStatusType::HIERARCHY,
+            FrontendStatusType::MODULATIONS,
+            FrontendStatusType::BANDWIDTH,
+            FrontendStatusType::GUARD_INTERVAL,
+            FrontendStatusType::TRANSMISSION_MODE,
+            FrontendStatusType::T2_SYSTEM_ID,
+            FrontendStatusType::DVBT_CELL_IDS,
+    };
+    mFrontendStatusCaps[4] = statusCaps;
+
+    FrontendCapabilities capsIsdbt;
+    FrontendIsdbtCapabilities isdbtCaps{
+            .modeCap = (int)FrontendIsdbtMode::MODE_1 | (int)FrontendIsdbtMode::MODE_2,
+            .bandwidthCap = (int)FrontendIsdbtBandwidth::BANDWIDTH_6MHZ,
+            .modulationCap = (int)FrontendIsdbtModulation::MOD_16QAM,
+            .coderateCap = (int)FrontendIsdbtCoderate::CODERATE_4_5 |
+                           (int)FrontendIsdbtCoderate::CODERATE_6_7,
+            .guardIntervalCap = (int)FrontendIsdbtGuardInterval::INTERVAL_1_128,
+            .timeInterleaveCap = (int)FrontendIsdbtTimeInterleaveMode::AUTO |
+                                 (int)FrontendIsdbtTimeInterleaveMode::INTERLEAVE_1_0,
+            .isSegmentAuto = true,
+            .isFullSegment = true,
+    };
+    capsIsdbt.set<FrontendCapabilities::Tag::isdbtCaps>(isdbtCaps);
+    mFrontendCaps[5] = capsIsdbt;
+    statusCaps = {
+            FrontendStatusType::AGC,
+            FrontendStatusType::LNA,
+            FrontendStatusType::MODULATION,
+            FrontendStatusType::MODULATIONS,
+            FrontendStatusType::BANDWIDTH,
+            FrontendStatusType::GUARD_INTERVAL,
+            FrontendStatusType::TRANSMISSION_MODE,
+            FrontendStatusType::ISDBT_SEGMENTS,
+            FrontendStatusType::ISDBT_MODE,
+            FrontendStatusType::ISDBT_PARTIAL_RECEPTION_FLAG,
+            FrontendStatusType::INTERLEAVINGS,
+    };
+    mFrontendStatusCaps[5] = statusCaps;
+
+    FrontendCapabilities capsAnalog;
+    capsAnalog.set<FrontendCapabilities::Tag::analogCaps>(FrontendAnalogCapabilities());
+    mFrontendCaps[6] = capsAnalog;
+    statusCaps = {
+            FrontendStatusType::LAYER_ERROR,
+            FrontendStatusType::MER,
+            FrontendStatusType::UEC,
+            FrontendStatusType::TS_DATA_RATES,
+    };
+    mFrontendStatusCaps[6] = statusCaps;
+
+    FrontendCapabilities capsAtsc;
+    capsAtsc.set<FrontendCapabilities::Tag::atscCaps>(FrontendAtscCapabilities());
+    mFrontendCaps[7] = capsAtsc;
+    statusCaps = {
+            FrontendStatusType::FREQ_OFFSET,
+            FrontendStatusType::RF_LOCK,
+            FrontendStatusType::MODULATIONS,
+            FrontendStatusType::IS_LINEAR,
+    };
+    mFrontendStatusCaps[7] = statusCaps;
+
+    FrontendCapabilities capsIsdbs3;
+    capsIsdbs3.set<FrontendCapabilities::Tag::isdbs3Caps>(FrontendIsdbs3Capabilities());
+    mFrontendCaps[8] = capsIsdbs3;
+    statusCaps = {
+            FrontendStatusType::DEMOD_LOCK,      FrontendStatusType::MODULATION,
+            FrontendStatusType::MODULATIONS,     FrontendStatusType::ROLL_OFF,
+            FrontendStatusType::IS_SHORT_FRAMES, FrontendStatusType::STREAM_ID_LIST,
+    };
+    mFrontendStatusCaps[8] = statusCaps;
+
+    FrontendCapabilities capsDtmb;
+    capsDtmb.set<FrontendCapabilities::Tag::dtmbCaps>(FrontendDtmbCapabilities());
+    mFrontendCaps[9] = capsDtmb;
+    statusCaps = {
+            FrontendStatusType::MODULATIONS,       FrontendStatusType::INTERLEAVINGS,
+            FrontendStatusType::BANDWIDTH,         FrontendStatusType::GUARD_INTERVAL,
+            FrontendStatusType::TRANSMISSION_MODE,
+    };
+    mFrontendStatusCaps[9] = statusCaps;
+
+    mLnbs.resize(2);
+    mLnbs[0] = ndk::SharedRefBase::make<Lnb>(0);
+    mLnbs[1] = ndk::SharedRefBase::make<Lnb>(1);
+}
+
+Tuner::~Tuner() {}
+
+::ndk::ScopedAStatus Tuner::getFrontendIds(std::vector<int32_t>* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    _aidl_return->resize(mFrontendSize);
+    for (int i = 0; i < mFrontendSize; i++) {
+        (*_aidl_return)[i] = mFrontends[i]->getFrontendId();
+    }
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Tuner::openFrontendById(int32_t in_frontendId,
+                                             std::shared_ptr<IFrontend>* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (in_frontendId >= mFrontendSize || in_frontendId < 0) {
+        ALOGW("[   WARN   ] Frontend with id %d isn't available", in_frontendId);
+        *_aidl_return = nullptr;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    *_aidl_return = mFrontends[in_frontendId];
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Tuner::openDemux(std::vector<int32_t>* out_demuxId,
+                                      std::shared_ptr<IDemux>* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    mLastUsedId += 1;
+    mDemuxes[mLastUsedId] = ndk::SharedRefBase::make<Demux>(mLastUsedId, this->ref<Tuner>());
+
+    out_demuxId->push_back(mLastUsedId);
+    *_aidl_return = mDemuxes[mLastUsedId];
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Tuner::getDemuxCaps(DemuxCapabilities* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    // IP filter can be an MMTP filter's data source.
+    _aidl_return->linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
+    // Support time filter testing
+    _aidl_return->bTimeFilter = true;
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Tuner::openDescrambler(std::shared_ptr<IDescrambler>* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    *_aidl_return = ndk::SharedRefBase::make<Descrambler>();
+
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Tuner::getFrontendInfo(int32_t in_frontendId, FrontendInfo* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (in_frontendId >= mFrontendSize) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    // assign randomly selected values for testing.
+    *_aidl_return = {
+            .type = mFrontends[in_frontendId]->getFrontendType(),
+            .minFrequency = 139000000,
+            .maxFrequency = 1139000000,
+            .minSymbolRate = 45,
+            .maxSymbolRate = 1145,
+            .acquireRange = 30,
+            .exclusiveGroupId = 57,
+            .statusCaps = mFrontendStatusCaps[in_frontendId],
+            .frontendCaps = mFrontendCaps[in_frontendId],
+    };
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Tuner::getLnbIds(std::vector<int32_t>* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    _aidl_return->resize(mLnbs.size());
+    for (int i = 0; i < mLnbs.size(); i++) {
+        (*_aidl_return)[i] = mLnbs[i]->getId();
+    }
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Tuner::openLnbById(int32_t in_lnbId, std::shared_ptr<ILnb>* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (in_lnbId >= mLnbs.size()) {
+        *_aidl_return = nullptr;
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    *_aidl_return = mLnbs[in_lnbId];
+    return ::ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<Frontend> Tuner::getFrontendById(int32_t frontendId) {
+    ALOGV("%s", __FUNCTION__);
+
+    return mFrontends[frontendId];
+}
+
+::ndk::ScopedAStatus Tuner::openLnbByName(const std::string& /* in_lnbName */,
+                                          std::vector<int32_t>* out_lnbId,
+                                          std::shared_ptr<ILnb>* _aidl_return) {
+    ALOGV("%s", __FUNCTION__);
+
+    out_lnbId->push_back(1234);
+    *_aidl_return = ndk::SharedRefBase::make<Lnb>();
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Tuner::setLna(bool /* in_bEnable */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+binder_status_t Tuner::dump(int fd, const char** args, uint32_t numArgs) {
+    ALOGV("%s", __FUNCTION__);
+    {
+        dprintf(fd, "Frontends:\n");
+        for (int i = 0; i < mFrontendSize; i++) {
+            mFrontends[i]->dump(fd, args, numArgs);
+            for (int j = 0; j < mFrontendStatusCaps[i].size(); j++) {
+                dprintf(fd, "    statusCap: %d\n", mFrontendStatusCaps[i][j]);
+            }
+        }
+    }
+    {
+        dprintf(fd, "Demuxs:\n");
+        map<int32_t, std::shared_ptr<Demux>>::iterator it;
+        for (it = mDemuxes.begin(); it != mDemuxes.end(); it++) {
+            it->second->dump(fd, args, numArgs);
+        }
+    }
+    {
+        dprintf(fd, "Lnbs:\n");
+        for (int i = 0; i < mLnbs.size(); i++) {
+            mLnbs[i]->dump(fd, args, numArgs);
+        }
+    }
+    return STATUS_OK;
+}
+
+void Tuner::setFrontendAsDemuxSource(int32_t frontendId, int32_t demuxId) {
+    mFrontendToDemux[frontendId] = demuxId;
+    if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
+        mDemuxes[demuxId]->startFrontendInputLoop();
+    }
+}
+
+void Tuner::removeDemux(int32_t demuxId) {
+    map<int32_t, int32_t>::iterator it;
+    for (it = mFrontendToDemux.begin(); it != mFrontendToDemux.end(); it++) {
+        if (it->second == demuxId) {
+            it = mFrontendToDemux.erase(it);
+            break;
+        }
+    }
+    mDemuxes.erase(demuxId);
+}
+
+void Tuner::removeFrontend(int32_t frontendId) {
+    map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
+    if (it != mFrontendToDemux.end()) {
+        mDemuxes.erase(it->second);
+    }
+    mFrontendToDemux.erase(frontendId);
+}
+
+void Tuner::frontendStopTune(int32_t frontendId) {
+    map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
+    int32_t demuxId;
+    if (it != mFrontendToDemux.end()) {
+        demuxId = it->second;
+        mDemuxes[demuxId]->stopFrontendInput();
+    }
+}
+
+void Tuner::frontendStartTune(int32_t frontendId) {
+    map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
+    int32_t demuxId;
+    if (it != mFrontendToDemux.end()) {
+        demuxId = it->second;
+        mDemuxes[demuxId]->startFrontendInputLoop();
+    }
+}
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/Tuner.h b/tv/tuner/aidl/default/Tuner.h
new file mode 100644
index 0000000..b33a1be
--- /dev/null
+++ b/tv/tuner/aidl/default/Tuner.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/BnTuner.h>
+#include <aidl/android/hardware/tv/tuner/FrontendCapabilities.h>
+
+#include <map>
+#include "Demux.h"
+#include "Frontend.h"
+#include "Lnb.h"
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+
+class Frontend;
+class Demux;
+class Lnb;
+
+class Tuner : public BnTuner {
+  public:
+    Tuner();
+    virtual ~Tuner();
+
+    ::ndk::ScopedAStatus getFrontendIds(std::vector<int32_t>* _aidl_return) override;
+    ::ndk::ScopedAStatus openFrontendById(int32_t in_frontendId,
+                                          std::shared_ptr<IFrontend>* _aidl_return) override;
+    ::ndk::ScopedAStatus openDemux(std::vector<int32_t>* out_demuxId,
+                                   std::shared_ptr<IDemux>* _aidl_return) override;
+    ::ndk::ScopedAStatus getDemuxCaps(DemuxCapabilities* _aidl_return) override;
+    ::ndk::ScopedAStatus openDescrambler(std::shared_ptr<IDescrambler>* _aidl_return) override;
+    ::ndk::ScopedAStatus getFrontendInfo(int32_t in_frontendId,
+                                         FrontendInfo* _aidl_return) override;
+    ::ndk::ScopedAStatus getLnbIds(std::vector<int32_t>* _aidl_return) override;
+    ::ndk::ScopedAStatus openLnbById(int32_t in_lnbId,
+                                     std::shared_ptr<ILnb>* _aidl_return) override;
+    ::ndk::ScopedAStatus openLnbByName(const std::string& in_lnbName,
+                                       std::vector<int32_t>* out_lnbId,
+                                       std::shared_ptr<ILnb>* _aidl_return) override;
+    ::ndk::ScopedAStatus setLna(bool in_bEnable) override;
+
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
+    std::shared_ptr<Frontend> getFrontendById(int32_t frontendId);
+    void setFrontendAsDemuxSource(int32_t frontendId, int32_t demuxId);
+    void frontendStartTune(int32_t frontendId);
+    void frontendStopTune(int32_t frontendId);
+    void removeDemux(int32_t demuxId);
+    void removeFrontend(int32_t frontendId);
+    void init();
+
+  private:
+    // Static mFrontends array to maintain local frontends information
+    map<int32_t, std::shared_ptr<Frontend>> mFrontends;
+    map<int32_t, FrontendCapabilities> mFrontendCaps;
+    map<int32_t, vector<FrontendStatusType>> mFrontendStatusCaps;
+    map<int32_t, int32_t> mFrontendToDemux;
+    map<int32_t, std::shared_ptr<Demux>> mDemuxes;
+    // To maintain how many Frontends we have
+    int mFrontendSize;
+    // The last used demux id. Initial value is -1.
+    // First used id will be 0.
+    int32_t mLastUsedId = -1;
+    vector<std::shared_ptr<Lnb>> mLnbs;
+};
+
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/tv/tuner/aidl/default/service.cpp b/tv/tuner/aidl/default/service.cpp
new file mode 100644
index 0000000..ac8d779
--- /dev/null
+++ b/tv/tuner/aidl/default/service.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.tv.tuner-service.example"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "Tuner.h"
+
+using ::aidl::android::hardware::tv::tuner::Tuner;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(8);
+    std::shared_ptr<Tuner> tuner = ndk::SharedRefBase::make<Tuner>();
+    tuner->init();
+
+    const std::string instance = std::string() + Tuner::descriptor + "/default";
+    binder_status_t status = AServiceManager_addService(tuner->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reached
+}
diff --git a/tv/tuner/aidl/default/tuner-default.rc b/tv/tuner/aidl/default/tuner-default.rc
new file mode 100644
index 0000000..d0248c2
--- /dev/null
+++ b/tv/tuner/aidl/default/tuner-default.rc
@@ -0,0 +1,7 @@
+service vendor.tuner-default /vendor/bin/hw/android.hardware.tv.tuner-service.example
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
+    onrestart restart media.tuner
diff --git a/tv/tuner/aidl/default/tuner-default.xml b/tv/tuner/aidl/default/tuner-default.xml
new file mode 100644
index 0000000..f0d03ad
--- /dev/null
+++ b/tv/tuner/aidl/default/tuner-default.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.tv.tuner</name>
+        <fqname>ITuner/default</fqname>
+    </hal>
+</manifest>
diff --git a/tv/tuner/aidl/vts/OWNERS b/tv/tuner/aidl/vts/OWNERS
new file mode 100644
index 0000000..bf2b609
--- /dev/null
+++ b/tv/tuner/aidl/vts/OWNERS
@@ -0,0 +1,3 @@
+hgchen@google.com
+shubang@google.com
+quxiangfang@google.com
diff --git a/tv/tuner/aidl/vts/functional/Android.bp b/tv/tuner/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..e5fb1e6
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/Android.bp
@@ -0,0 +1,77 @@
+//
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalTvTunerTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "DemuxTests.cpp",
+        "DescramblerTests.cpp",
+        "DvrTests.cpp",
+        "FilterTests.cpp",
+        "FrontendTests.cpp",
+        "LnbTests.cpp",
+        "VtsHalTvTunerTargetTest.cpp",
+    ],
+    generated_headers: [
+        "tuner_testing_dynamic_configuration_V1_0_enums",
+        "tuner_testing_dynamic_configuration_V1_0_parser",
+    ],
+    generated_sources: [
+        "tuner_testing_dynamic_configuration_V1_0_enums",
+        "tuner_testing_dynamic_configuration_V1_0_parser",
+    ],
+    header_libs: ["libxsdc-utils"],
+    static_libs: [
+        "android.hardware.cas@1.0",
+        "android.hardware.cas@1.1",
+        "android.hardware.cas@1.2",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+        "android.hardware.tv.tuner-V1-ndk",
+        "libaidlcommonsupport",
+        "libfmq",
+        "libcutils",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libvndksupport",
+        "libxml2",
+    ],
+    data: [
+        ":tuner_frontend_input_ts",
+        ":tuner_frontend_input_es",
+        ":tuner_testing_dynamic_configuration_V1_0",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+
+    require_root: true,
+}
diff --git a/tv/tuner/aidl/vts/functional/AndroidTest.xml b/tv/tuner/aidl/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..a849e5a
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/AndroidTest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalTvTunerTargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalTvTunerTargetTest->/data/local/tmp/VtsHalTvTunerTargetTest" />
+        <option name="push" value="test.es->/data/local/tmp/test.es" />
+        <option name="push" value="segment000000.ts->/data/local/tmp/segment000000.ts" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalTvTunerTargetTest" />
+        <option name="native-test-timeout" value="30m" />
+    </test>
+</configuration>
diff --git a/tv/tuner/aidl/vts/functional/DemuxTests.cpp b/tv/tuner/aidl/vts/functional/DemuxTests.cpp
new file mode 100644
index 0000000..9de01e1
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/DemuxTests.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#include "DemuxTests.h"
+
+AssertionResult DemuxTests::openDemux(std::shared_ptr<IDemux>& demux, int32_t& demuxId) {
+    std::vector<int32_t> id;
+    auto status = mService->openDemux(&id, &mDemux);
+    if (status.isOk()) {
+        demux = mDemux;
+        demuxId = id[0];
+    }
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DemuxTests::setDemuxFrontendDataSource(int32_t frontendId) {
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    auto status = mDemux->setFrontendDataSource(frontendId);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DemuxTests::getDemuxCaps(DemuxCapabilities& demuxCaps) {
+    if (!mDemux) {
+        ALOGW("[vts] Test with openDemux first.");
+        return failure();
+    }
+    auto status = mService->getDemuxCaps(&demuxCaps);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DemuxTests::getAvSyncId(std::shared_ptr<IFilter> filter, int32_t& avSyncHwId) {
+    EXPECT_TRUE(mDemux) << "Demux is not opened yet.";
+
+    auto status = mDemux->getAvSyncHwId(filter, &avSyncHwId);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DemuxTests::getAvSyncTime(int32_t avSyncId) {
+    EXPECT_TRUE(mDemux) << "Demux is not opened yet.";
+
+    int64_t syncTime;
+    auto status = mDemux->getAvSyncTime(avSyncId, &syncTime);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DemuxTests::closeDemux() {
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    auto status = mDemux->close();
+    mDemux = nullptr;
+    return AssertionResult(status.isOk());
+}
diff --git a/tv/tuner/aidl/vts/functional/DemuxTests.h b/tv/tuner/aidl/vts/functional/DemuxTests.h
new file mode 100644
index 0000000..7698de3
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/DemuxTests.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/DemuxCapabilities.h>
+#include <aidl/android/hardware/tv/tuner/IDemux.h>
+#include <aidl/android/hardware/tv/tuner/IFilter.h>
+#include <aidl/android/hardware/tv/tuner/ITuner.h>
+
+#include <gtest/gtest.h>
+#include <log/log.h>
+
+using ::testing::AssertionResult;
+
+using namespace aidl::android::hardware::tv::tuner;
+
+class DemuxTests {
+  public:
+    void setService(std::shared_ptr<ITuner> tuner) { mService = tuner; }
+
+    AssertionResult openDemux(std::shared_ptr<IDemux>& demux, int32_t& demuxId);
+    AssertionResult setDemuxFrontendDataSource(int32_t frontendId);
+    AssertionResult getAvSyncId(std::shared_ptr<IFilter> filter, int32_t& avSyncHwId);
+    AssertionResult getAvSyncTime(int32_t avSyncId);
+    AssertionResult getDemuxCaps(DemuxCapabilities& demuxCaps);
+    AssertionResult closeDemux();
+
+  protected:
+    static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+    static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+    std::shared_ptr<ITuner> mService;
+    std::shared_ptr<IDemux> mDemux;
+};
diff --git a/tv/tuner/aidl/vts/functional/DescramblerTests.cpp b/tv/tuner/aidl/vts/functional/DescramblerTests.cpp
new file mode 100644
index 0000000..157fa04
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/DescramblerTests.cpp
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+
+#include "DescramblerTests.h"
+
+using namespace std;
+
+AssertionResult DescramblerTests::createCasPlugin(int32_t caSystemId) {
+    auto status = mMediaCasService->isSystemIdSupported(caSystemId);
+    if (!status.isOk() || !status) {
+        ALOGW("[vts] Failed to check isSystemIdSupported.");
+        return failure();
+    }
+
+    mCasListener = new MediaCasListener();
+    auto pluginStatus = mMediaCasService->createPluginExt(caSystemId, mCasListener);
+    if (!pluginStatus.isOk()) {
+        ALOGW("[vts] Failed to createPluginExt.");
+        return failure();
+    }
+    mCas = ICas::castFrom(pluginStatus);
+    if (mCas == nullptr) {
+        ALOGW("[vts] Failed to get ICas.");
+        return failure();
+    }
+    return success();
+}
+
+AssertionResult DescramblerTests::openCasSession(vector<uint8_t>& sessionId,
+                                                 vector<uint8_t>& hidlPvtData) {
+    Status sessionStatus;
+    SessionIntent intent = SessionIntent::LIVE;
+    ScramblingMode mode = ScramblingMode::RESERVED;
+    auto returnVoid =
+            mCas->openSession_1_2(intent, mode, [&](Status status, const hidl_vec<uint8_t>& id) {
+                sessionStatus = status;
+                sessionId = id;
+            });
+    if (!returnVoid.isOk() || (sessionStatus != Status::OK)) {
+        ALOGW("[vts] Failed to open cas session.");
+        mCas->closeSession(sessionId);
+        return failure();
+    }
+
+    if (hidlPvtData.size() > 0) {
+        auto status = mCas->setSessionPrivateData(sessionId, hidlPvtData);
+        if (status != android::hardware::cas::V1_0::Status::OK) {
+            ALOGW("[vts] Failed to set session private data");
+            mCas->closeSession(sessionId);
+            return failure();
+        }
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::getKeyToken(int32_t caSystemId, string& provisonStr,
+                                              vector<uint8_t>& hidlPvtData,
+                                              vector<uint8_t>& token) {
+    if (createCasPlugin(caSystemId) != success()) {
+        ALOGW("[vts] createCasPlugin failed.");
+        return failure();
+    }
+
+    if (provisonStr.size() > 0) {
+        auto returnStatus = mCas->provision(hidl_string(provisonStr));
+        if (returnStatus != android::hardware::cas::V1_0::Status::OK) {
+            ALOGW("[vts] provision failed.");
+            return failure();
+        }
+    }
+
+    return openCasSession(token, hidlPvtData);
+}
+
+AssertionResult DescramblerTests::openDescrambler(int32_t demuxId) {
+    ndk::ScopedAStatus status;
+    status = mService->openDescrambler(&mDescrambler);
+    if (!status.isOk()) {
+        ALOGW("[vts] openDescrambler failed.");
+        return failure();
+    }
+
+    status = mDescrambler->setDemuxSource(demuxId);
+    if (!status.isOk()) {
+        ALOGW("[vts] setDemuxSource failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::setKeyToken(vector<uint8_t>& token) {
+    ndk::ScopedAStatus status;
+    if (!mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->setKeyToken(token);
+    if (!status.isOk()) {
+        ALOGW("[vts] setKeyToken failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::addPid(DemuxPid pid,
+                                         std::shared_ptr<IFilter> optionalSourceFilter) {
+    ndk::ScopedAStatus status;
+    if (!mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->addPid(pid, optionalSourceFilter);
+    if (!status.isOk()) {
+        ALOGW("[vts] addPid failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::removePid(DemuxPid pid,
+                                            std::shared_ptr<IFilter> optionalSourceFilter) {
+    ndk::ScopedAStatus status;
+    if (!mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->removePid(pid, optionalSourceFilter);
+    if (!status.isOk()) {
+        ALOGW("[vts] removePid failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::closeDescrambler() {
+    ndk::ScopedAStatus status;
+    if (!mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->close();
+    mDescrambler = nullptr;
+    if (!status.isOk()) {
+        ALOGW("[vts] close Descrambler failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::getDemuxPidFromFilterSettings(DemuxFilterType type,
+                                                                const DemuxFilterSettings& settings,
+                                                                DemuxPid& pid) {
+    switch (type.mainType) {
+        case DemuxFilterMainType::TS:
+            if (type.subType.get<DemuxFilterSubType::Tag::tsFilterType>() ==
+                        DemuxTsFilterType::AUDIO ||
+                type.subType.get<DemuxFilterSubType::Tag::tsFilterType>() ==
+                        DemuxTsFilterType::VIDEO) {
+                pid.set<DemuxPid::Tag::tPid>(settings.get<DemuxFilterSettings::Tag::ts>().tpid);
+            } else {
+                ALOGW("[vts] Not a media ts filter!");
+                return failure();
+            }
+            break;
+        case DemuxFilterMainType::MMTP:
+            if (type.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>() ==
+                        DemuxMmtpFilterType::AUDIO ||
+                type.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>() ==
+                        DemuxMmtpFilterType::VIDEO) {
+                pid.set<DemuxPid::Tag::mmtpPid>(
+                        settings.get<DemuxFilterSettings::Tag::mmtp>().mmtpPid);
+            } else {
+                ALOGW("[vts] Not a media mmtp filter!");
+                return failure();
+            }
+            break;
+        default:
+            ALOGW("[vts] Not a media filter!");
+            return failure();
+    }
+    return success();
+}
diff --git a/tv/tuner/aidl/vts/functional/DescramblerTests.h b/tv/tuner/aidl/vts/functional/DescramblerTests.h
new file mode 100644
index 0000000..f0b7691
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/DescramblerTests.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <fstream>
+#include <iostream>
+#include <map>
+
+#include <android/hardware/cas/1.0/types.h>
+#include <android/hardware/cas/1.2/ICas.h>
+#include <android/hardware/cas/1.2/ICasListener.h>
+#include <android/hardware/cas/1.2/IMediaCasService.h>
+#include <android/hardware/cas/1.2/types.h>
+
+#include <aidl/android/hardware/tv/tuner/IDescrambler.h>
+#include <aidl/android/hardware/tv/tuner/IDvr.h>
+#include <aidl/android/hardware/tv/tuner/IDvrCallback.h>
+#include <aidl/android/hardware/tv/tuner/ITuner.h>
+
+using android::Condition;
+using android::Mutex;
+using android::sp;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::cas::V1_2::ICas;
+using android::hardware::cas::V1_2::ICasListener;
+using android::hardware::cas::V1_2::IMediaCasService;
+using android::hardware::cas::V1_2::ScramblingMode;
+using android::hardware::cas::V1_2::SessionIntent;
+using android::hardware::cas::V1_2::Status;
+using android::hardware::cas::V1_2::StatusEvent;
+
+using ::testing::AssertionResult;
+
+using namespace aidl::android::hardware::tv::tuner;
+
+class MediaCasListener : public ICasListener {
+  public:
+    virtual Return<void> onEvent(int32_t /*event*/, int32_t /*arg*/,
+                                 const hidl_vec<uint8_t>& /*data*/) override {
+        return Void();
+    }
+
+    virtual Return<void> onSessionEvent(const hidl_vec<uint8_t>& /*sessionId*/, int32_t /*event*/,
+                                        int32_t /*arg*/,
+                                        const hidl_vec<uint8_t>& /*data*/) override {
+        return Void();
+    }
+
+    virtual Return<void> onStatusUpdate(StatusEvent /*event*/, int32_t /*arg*/) override {
+        return Void();
+    }
+};
+
+class DescramblerTests {
+  public:
+    void setService(std::shared_ptr<ITuner> tuner) { mService = tuner; }
+    void setCasService(sp<IMediaCasService> casService) { mMediaCasService = casService; }
+
+    AssertionResult setKeyToken(std::vector<uint8_t>& token);
+    AssertionResult openDescrambler(int32_t demuxId);
+    AssertionResult addPid(DemuxPid pid, std::shared_ptr<IFilter> optionalSourceFilter);
+    AssertionResult removePid(DemuxPid pid, std::shared_ptr<IFilter> optionalSourceFilter);
+    AssertionResult closeDescrambler();
+    AssertionResult getKeyToken(int32_t caSystemId, std::string& provisonStr,
+                                std::vector<uint8_t>& hidlPvtData, std::vector<uint8_t>& token);
+    AssertionResult getDemuxPidFromFilterSettings(DemuxFilterType type,
+                                                  const DemuxFilterSettings& settings,
+                                                  DemuxPid& pid);
+
+  protected:
+    static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+    static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+    std::shared_ptr<ITuner> mService;
+    std::shared_ptr<IDescrambler> mDescrambler;
+    android::sp<ICas> mCas;
+    android::sp<IMediaCasService> mMediaCasService;
+    android::sp<MediaCasListener> mCasListener;
+
+  private:
+    AssertionResult openCasSession(std::vector<uint8_t>& sessionId,
+                                   std::vector<uint8_t>& hidlPvtData);
+    AssertionResult createCasPlugin(int32_t caSystemId);
+};
diff --git a/tv/tuner/aidl/vts/functional/DvrTests.cpp b/tv/tuner/aidl/vts/functional/DvrTests.cpp
new file mode 100644
index 0000000..a9c3b51
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/DvrTests.cpp
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+#include "DvrTests.h"
+
+#include <aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.h>
+
+void DvrCallback::startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings,
+                                           MQDesc& playbackMQDescriptor) {
+    mInputDataFile = dataInputFile;
+    mPlaybackSettings = settings;
+    mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */);
+    EXPECT_TRUE(mPlaybackMQ);
+
+    mPlaybackThread = std::thread(&DvrCallback::playbackThreadLoop, this);
+}
+
+void DvrCallback::stopPlaybackThread() {
+    mPlaybackThreadRunning = false;
+    mKeepWritingPlaybackFMQ = false;
+
+    if (mPlaybackThread.joinable()) {
+        mPlaybackThread.join();
+    }
+}
+
+void DvrCallback::playbackThreadLoop() {
+    mPlaybackThreadRunning = true;
+    mKeepWritingPlaybackFMQ = true;
+
+    // Create the EventFlag that is used to signal the HAL impl that data have been
+    // written into the Playback FMQ
+    EventFlag* playbackMQEventFlag;
+    EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) ==
+                android::OK);
+
+    int fd = open(mInputDataFile.c_str(), O_RDONLY | O_LARGEFILE);
+    int readBytes;
+    uint32_t regionSize = 0;
+    int8_t* buffer;
+    ALOGW("[vts] playback thread loop start %s", mInputDataFile.c_str());
+    if (fd < 0) {
+        mPlaybackThreadRunning = false;
+        ALOGW("[vts] Error %s", strerror(errno));
+    }
+
+    while (mPlaybackThreadRunning) {
+        while (mKeepWritingPlaybackFMQ) {
+            int totalWrite = mPlaybackMQ->availableToWrite();
+            if (totalWrite * 4 < mPlaybackMQ->getQuantumCount()) {
+                // Wait for the HAL implementation to read more data then write.
+                continue;
+            }
+            AidlMessageQueue<int8_t, SynchronizedReadWrite>::MemTransaction memTx;
+            if (!mPlaybackMQ->beginWrite(totalWrite, &memTx)) {
+                ALOGW("[vts] Fail to write into Playback fmq.");
+                mPlaybackThreadRunning = false;
+                break;
+            }
+            auto first = memTx.getFirstRegion();
+            buffer = first.getAddress();
+            regionSize = first.getLength();
+
+            if (regionSize > 0) {
+                readBytes = read(fd, buffer, regionSize);
+                if (readBytes <= 0) {
+                    if (readBytes < 0) {
+                        ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str());
+                    } else {
+                        ALOGW("[vts] playback input EOF.");
+                    }
+                    mPlaybackThreadRunning = false;
+                    break;
+                }
+            }
+            if (regionSize == 0 || (readBytes == regionSize && regionSize < totalWrite)) {
+                auto second = memTx.getSecondRegion();
+                buffer = second.getAddress();
+                regionSize = second.getLength();
+                int ret = read(fd, buffer, regionSize);
+                if (ret <= 0) {
+                    if (ret < 0) {
+                        ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str());
+                    } else {
+                        ALOGW("[vts] playback input EOF.");
+                    }
+                    mPlaybackThreadRunning = false;
+                    break;
+                }
+                readBytes += ret;
+            }
+            if (!mPlaybackMQ->commitWrite(readBytes)) {
+                ALOGW("[vts] Failed to commit write playback fmq.");
+                mPlaybackThreadRunning = false;
+                break;
+            }
+            playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
+        }
+    }
+
+    mPlaybackThreadRunning = false;
+    ALOGW("[vts] Playback thread end.");
+    close(fd);
+}
+
+void DvrCallback::testRecordOutput() {
+    bool passed = true;
+    {
+        android::Mutex::Autolock autoLock(mMsgLock);
+        while (mDataOutputBuffer.empty()) {
+            if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+                EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
+                passed = false;
+                break;
+            }
+        }
+    }
+    stopRecordThread();
+    if (passed) ALOGW("[vts] record pass and stop");
+}
+
+void DvrCallback::startRecordOutputThread(RecordSettings /* recordSettings */,
+                                          MQDesc& recordMQDescriptor) {
+    mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */);
+    EXPECT_TRUE(mRecordMQ);
+
+    mRecordThread = std::thread(&DvrCallback::recordThreadLoop, this);
+}
+
+void DvrCallback::recordThreadLoop() {
+    ALOGD("[vts] DvrCallback record threadLoop start.");
+    mRecordThreadRunning = true;
+    mKeepReadingRecordFMQ = true;
+
+    // Create the EventFlag that is used to signal the HAL impl that data have been
+    // read from the Record FMQ
+    EventFlag* recordMQEventFlag;
+    EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) ==
+                android::OK);
+
+    while (mRecordThreadRunning) {
+        while (mKeepReadingRecordFMQ) {
+            uint32_t efState = 0;
+            android::status_t status = recordMQEventFlag->wait(
+                    static_cast<int32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
+                    true /* retry on spurious wake */);
+            if (status != android::OK) {
+                ALOGD("[vts] wait for data ready on the record FMQ");
+                continue;
+            }
+            // Our current implementation filter the data and write it into the filter FMQ
+            // immediately after the DATA_READY from the VTS/framework
+            if (!readRecordFMQ()) {
+                ALOGD("[vts] record data failed to be filtered. Ending thread");
+                mRecordThreadRunning = false;
+                break;
+            }
+        }
+    }
+
+    mRecordThreadRunning = false;
+    ALOGD("[vts] record thread ended.");
+}
+
+bool DvrCallback::readRecordFMQ() {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    bool result = false;
+    int readSize = mRecordMQ->availableToRead();
+    mDataOutputBuffer.clear();
+    mDataOutputBuffer.resize(readSize);
+    result = mRecordMQ->read(mDataOutputBuffer.data(), readSize);
+    EXPECT_TRUE(result) << "can't read from Record MQ";
+    mMsgCondition.signal();
+    return result;
+}
+
+void DvrCallback::stopRecordThread() {
+    mKeepReadingRecordFMQ = false;
+    mRecordThreadRunning = false;
+
+    if (mRecordThread.joinable()) {
+        mRecordThread.join();
+    }
+}
+
+AssertionResult DvrTests::openDvrInDemux(DvrType type, int32_t bufferSize) {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+
+    // Create dvr callback
+    if (type == DvrType::PLAYBACK) {
+        mDvrPlaybackCallback = ndk::SharedRefBase::make<DvrCallback>();
+        status = mDemux->openDvr(type, bufferSize, mDvrPlaybackCallback, &mDvrPlayback);
+        if (status.isOk()) {
+            mDvrPlaybackCallback->setDvr(mDvrPlayback);
+        }
+    }
+
+    if (type == DvrType::RECORD) {
+        mDvrRecordCallback = ndk::SharedRefBase::make<DvrCallback>();
+        status = mDemux->openDvr(type, bufferSize, mDvrRecordCallback, &mDvrRecord);
+        if (status.isOk()) {
+            mDvrRecordCallback->setDvr(mDvrRecord);
+        }
+    }
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DvrTests::configDvrPlayback(DvrSettings setting) {
+    ndk::ScopedAStatus status = mDvrPlayback->configure(setting);
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DvrTests::configDvrRecord(DvrSettings setting) {
+    ndk::ScopedAStatus status = mDvrRecord->configure(setting);
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DvrTests::getDvrPlaybackMQDescriptor() {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
+
+    status = mDvrPlayback->getQueueDesc(&mDvrPlaybackMQDescriptor);
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DvrTests::getDvrRecordMQDescriptor() {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    status = mDvrRecord->getQueueDesc(&mDvrRecordMQDescriptor);
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DvrTests::attachFilterToDvr(std::shared_ptr<IFilter> filter) {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    status = mDvrRecord->attachFilter(filter);
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DvrTests::detachFilterToDvr(std::shared_ptr<IFilter> filter) {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    status = mDvrRecord->detachFilter(filter);
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DvrTests::startDvrPlayback() {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
+
+    status = mDvrPlayback->start();
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DvrTests::stopDvrPlayback() {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
+
+    status = mDvrPlayback->stop();
+
+    return AssertionResult(status.isOk());
+}
+
+void DvrTests::closeDvrPlayback() {
+    ASSERT_TRUE(mDemux);
+    ASSERT_TRUE(mDvrPlayback);
+    ASSERT_TRUE(mDvrPlayback->close().isOk());
+}
+
+AssertionResult DvrTests::startDvrRecord() {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    status = mDvrRecord->start();
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DvrTests::stopDvrRecord() {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    status = mDvrRecord->stop();
+
+    return AssertionResult(status.isOk());
+}
+
+void DvrTests::closeDvrRecord() {
+    ASSERT_TRUE(mDemux);
+    ASSERT_TRUE(mDvrRecord);
+    ASSERT_TRUE(mDvrRecord->close().isOk());
+}
diff --git a/tv/tuner/aidl/vts/functional/DvrTests.h b/tv/tuner/aidl/vts/functional/DvrTests.h
new file mode 100644
index 0000000..6662637
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/DvrTests.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <fcntl.h>
+#include <fmq/AidlMessageQueue.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <atomic>
+#include <fstream>
+#include <iostream>
+#include <map>
+#include <thread>
+
+#include <aidl/android/hardware/tv/tuner/BnDvrCallback.h>
+#include <aidl/android/hardware/tv/tuner/IDvr.h>
+#include <aidl/android/hardware/tv/tuner/ITuner.h>
+
+#include "FilterTests.h"
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::Condition;
+using ::android::Mutex;
+using ::android::hardware::EventFlag;
+
+using namespace aidl::android::hardware::tv::tuner;
+using namespace std;
+
+#define WAIT_TIMEOUT 3000000000
+
+class DvrCallback : public BnDvrCallback {
+  public:
+    virtual ::ndk::ScopedAStatus onRecordStatus(RecordStatus status) override {
+        ALOGD("[vts] record status %hhu", status);
+        switch (status) {
+            case RecordStatus::DATA_READY:
+                break;
+            case RecordStatus::LOW_WATER:
+                break;
+            case RecordStatus::HIGH_WATER:
+            case RecordStatus::OVERFLOW:
+                ALOGD("[vts] record overflow. Flushing.");
+                EXPECT_TRUE(mDvr) << "Dvr callback is not set with an IDvr";
+                if (mDvr) {
+                    ndk::ScopedAStatus result = mDvr->flush();
+                    ALOGD("[vts] Flushing result %s.", result.getMessage());
+                }
+                break;
+        }
+        return ndk::ScopedAStatus::ok();
+    }
+
+    virtual ::ndk::ScopedAStatus onPlaybackStatus(PlaybackStatus status) override {
+        // android::Mutex::Autolock autoLock(mMsgLock);
+        ALOGD("[vts] playback status %d", status);
+        switch (status) {
+            case PlaybackStatus::SPACE_EMPTY:
+            case PlaybackStatus::SPACE_ALMOST_EMPTY:
+                ALOGD("[vts] keep playback inputing %d", status);
+                mKeepWritingPlaybackFMQ = true;
+                break;
+            case PlaybackStatus::SPACE_ALMOST_FULL:
+            case PlaybackStatus::SPACE_FULL:
+                ALOGD("[vts] stop playback inputing %d", status);
+                mKeepWritingPlaybackFMQ = false;
+                break;
+        }
+        return ndk::ScopedAStatus::ok();
+    }
+
+    void stopPlaybackThread();
+    void testRecordOutput();
+    void stopRecordThread();
+
+    void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings,
+                                  MQDesc& playbackMQDescriptor);
+    void startRecordOutputThread(RecordSettings recordSettings, MQDesc& recordMQDescriptor);
+    static void* __threadLoopPlayback(void* user);
+    static void* __threadLoopRecord(void* threadArgs);
+    void playbackThreadLoop();
+    void recordThreadLoop();
+
+    bool readRecordFMQ();
+
+    void setDvr(std::shared_ptr<IDvr> dvr) { mDvr = dvr; }
+
+  private:
+    struct RecordThreadArgs {
+        DvrCallback* user;
+        RecordSettings* recordSettings;
+        bool* keepReadingRecordFMQ;
+    };
+    // uint16_t mDataLength = 0;
+    std::vector<int8_t> mDataOutputBuffer;
+
+    std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterMQ;
+    std::unique_ptr<FilterMQ> mPlaybackMQ;
+    std::unique_ptr<FilterMQ> mRecordMQ;
+    std::map<uint32_t, EventFlag*> mFilterMQEventFlag;
+
+    android::Mutex mMsgLock;
+    android::Condition mMsgCondition;
+
+    std::atomic<bool> mKeepWritingPlaybackFMQ = true;
+    std::atomic<bool> mKeepReadingRecordFMQ = true;
+    std::atomic<bool> mPlaybackThreadRunning;
+    std::atomic<bool> mRecordThreadRunning;
+    std::thread mPlaybackThread;
+    std::thread mRecordThread;
+    string mInputDataFile;
+    PlaybackSettings mPlaybackSettings;
+
+    std::shared_ptr<IDvr> mDvr = nullptr;
+
+    // int mPidFilterOutputCount = 0;
+};
+
+class DvrTests {
+  public:
+    void setService(std::shared_ptr<ITuner> tuner) { mService = tuner; }
+    void setDemux(std::shared_ptr<IDemux> demux) { mDemux = demux; }
+
+    void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings) {
+        mDvrPlaybackCallback->startPlaybackInputThread(dataInputFile, settings,
+                                                       mDvrPlaybackMQDescriptor);
+    };
+
+    void startRecordOutputThread(RecordSettings settings) {
+        mDvrRecordCallback->startRecordOutputThread(settings, mDvrRecordMQDescriptor);
+    };
+
+    void stopPlaybackThread() { mDvrPlaybackCallback->stopPlaybackThread(); }
+    void testRecordOutput() { mDvrRecordCallback->testRecordOutput(); }
+    void stopRecordThread() { mDvrRecordCallback->stopRecordThread(); }
+
+    AssertionResult openDvrInDemux(DvrType type, int32_t bufferSize);
+    AssertionResult configDvrPlayback(DvrSettings setting);
+    AssertionResult configDvrRecord(DvrSettings setting);
+    AssertionResult getDvrPlaybackMQDescriptor();
+    AssertionResult getDvrRecordMQDescriptor();
+    AssertionResult attachFilterToDvr(std::shared_ptr<IFilter> filter);
+    AssertionResult detachFilterToDvr(std::shared_ptr<IFilter> filter);
+    AssertionResult stopDvrPlayback();
+    AssertionResult startDvrPlayback();
+    AssertionResult stopDvrRecord();
+    AssertionResult startDvrRecord();
+    void closeDvrPlayback();
+    void closeDvrRecord();
+
+  protected:
+    static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+    static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+    std::shared_ptr<ITuner> mService;
+    std::shared_ptr<IDvr> mDvrPlayback;
+    std::shared_ptr<IDvr> mDvrRecord;
+    std::shared_ptr<IDemux> mDemux;
+    std::shared_ptr<DvrCallback> mDvrPlaybackCallback;
+    std::shared_ptr<DvrCallback> mDvrRecordCallback;
+    MQDesc mDvrPlaybackMQDescriptor;
+    MQDesc mDvrRecordMQDescriptor;
+};
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.cpp b/tv/tuner/aidl/vts/functional/FilterTests.cpp
new file mode 100644
index 0000000..53afef7
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/FilterTests.cpp
@@ -0,0 +1,391 @@
+/*
+ * 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.
+ */
+
+#include "FilterTests.h"
+
+#include <inttypes.h>
+#include <algorithm>
+
+#include <aidl/android/hardware/tv/tuner/DemuxFilterMonitorEventType.h>
+#include <aidlcommonsupport/NativeHandle.h>
+
+using ::aidl::android::hardware::common::NativeHandle;
+
+::ndk::ScopedAStatus FilterCallback::onFilterEvent(const vector<DemuxFilterEvent>& events) {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    // Temprarily we treat the first coming back filter data on the matching pid a success
+    // once all of the MQ are cleared, means we got all the expected output
+    readFilterEventsData(events);
+    mPidFilterOutputCount++;
+    mMsgCondition.signal();
+
+    for (auto it = mFilterCallbackVerifiers.begin(); it != mFilterCallbackVerifiers.end();) {
+        auto& [verifier, promise] = *it;
+        if (verifier(events)) {
+            promise.set_value();
+            it = mFilterCallbackVerifiers.erase(it);
+        } else {
+            ++it;
+        }
+    };
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+std::future<void> FilterCallback::verifyFilterCallback(FilterCallbackVerifier&& verifier) {
+    std::promise<void> promise;
+    auto future = promise.get_future();
+    mFilterCallbackVerifiers.emplace_back(std::move(verifier), std::move(promise));
+    return future;
+}
+
+void FilterCallback::testFilterDataOutput() {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    while (mPidFilterOutputCount < 1) {
+        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+            EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
+            return;
+        }
+    }
+    mPidFilterOutputCount = 0;
+    ALOGW("[vts] pass and stop");
+}
+
+void FilterCallback::testFilterScramblingEvent() {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    while (mScramblingStatusEvent < 1) {
+        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+            EXPECT_TRUE(false) << "scrambling event does not output within timeout";
+            return;
+        }
+    }
+    mScramblingStatusEvent = 0;
+    ALOGW("[vts] pass and stop");
+}
+
+void FilterCallback::testFilterIpCidEvent() {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    while (mIpCidEvent < 1) {
+        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+            EXPECT_TRUE(false) << "ip cid change event does not output within timeout";
+            return;
+        }
+    }
+    mIpCidEvent = 0;
+    ALOGW("[vts] pass and stop");
+}
+
+void FilterCallback::testStartIdAfterReconfigure() {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    while (!mStartIdReceived) {
+        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+            EXPECT_TRUE(false) << "does not receive start id within timeout";
+            return;
+        }
+    }
+    mStartIdReceived = false;
+    ALOGW("[vts] pass and stop");
+}
+
+void FilterCallback::readFilterEventsData(const vector<DemuxFilterEvent>& events) {
+    ALOGW("[vts] reading filter event");
+    // todo separate filter handlers
+    for (int i = 0; i < events.size(); i++) {
+        switch (events[i].getTag()) {
+            case DemuxFilterEvent::Tag::media:
+                ALOGD("[vts] Media filter event, avMemHandle numFds=%zu.",
+                      events[i].get<DemuxFilterEvent::Tag::media>().avMemory.fds.size());
+                dumpAvData(events[i].get<DemuxFilterEvent::Tag::media>());
+                break;
+            case DemuxFilterEvent::Tag::tsRecord:
+                ALOGD("[vts] TS record filter event, pts=%" PRIu64 ", firstMbInSlice=%d",
+                      events[i].get<DemuxFilterEvent::Tag::tsRecord>().pts,
+                      events[i].get<DemuxFilterEvent::Tag::tsRecord>().firstMbInSlice);
+                break;
+            case DemuxFilterEvent::Tag::mmtpRecord:
+                ALOGD("[vts] MMTP record filter event, pts=%" PRIu64
+                      ", firstMbInSlice=%d, mpuSequenceNumber=%d, tsIndexMask=%d",
+                      events[i].get<DemuxFilterEvent::Tag::mmtpRecord>().pts,
+                      events[i].get<DemuxFilterEvent::Tag::mmtpRecord>().firstMbInSlice,
+                      events[i].get<DemuxFilterEvent::Tag::mmtpRecord>().mpuSequenceNumber,
+                      events[i].get<DemuxFilterEvent::Tag::mmtpRecord>().tsIndexMask);
+                break;
+            case DemuxFilterEvent::Tag::monitorEvent:
+                switch (events[i].get<DemuxFilterEvent::Tag::monitorEvent>().getTag()) {
+                    case DemuxFilterMonitorEvent::Tag::scramblingStatus:
+                        mScramblingStatusEvent++;
+                        break;
+                    case DemuxFilterMonitorEvent::Tag::cid:
+                        mIpCidEvent++;
+                        break;
+                    default:
+                        break;
+                }
+                break;
+            case DemuxFilterEvent::Tag::startId:
+                ALOGD("[vts] Restart filter event, startId=%d",
+                      events[i].get<DemuxFilterEvent::Tag::startId>());
+                mStartIdReceived = true;
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+bool FilterCallback::dumpAvData(const DemuxFilterMediaEvent& event) {
+    int64_t length = event.dataLength;
+    int64_t offset = event.offset;
+    int av_fd;
+    // read data from buffer pointed by a handle
+    if (event.avMemory.fds.size() == 0) {
+        if (mAvSharedHandle == nullptr) {
+            return false;
+        }
+        av_fd = mAvSharedHandle->data[0];
+    } else {
+        av_fd = event.avMemory.fds[0].get();
+    }
+    uint8_t* buffer = static_cast<uint8_t*>(
+            mmap(NULL, length + offset, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0));
+    if (buffer == MAP_FAILED) {
+        ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
+        return false;
+    }
+    uint8_t output[length + 1];
+    memcpy(output, buffer + offset, length);
+    // print buffer and check with golden output.
+    return true;
+}
+
+AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, int32_t bufferSize) {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+
+    // Create demux callback
+    mFilterCallback = ndk::SharedRefBase::make<FilterCallback>();
+
+    // Add filter to the local demux
+    status = mDemux->openFilter(type, bufferSize, mFilterCallback, &mFilter);
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::getNewlyOpenedFilterId_64bit(int64_t& filterId) {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mFilter) << "Test with openFilterInDemux first.";
+    EXPECT_TRUE(mFilterCallback) << "Test with openFilterInDemux first.";
+
+    status = mFilter->getId64Bit(&mFilterId);
+    if (status.isOk()) {
+        mFilterCallback->setFilterId(mFilterId);
+        mFilterCallback->setFilterInterface(mFilter);
+        mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
+        mFilters[mFilterId] = mFilter;
+        mFilterCallbacks[mFilterId] = mFilterCallback;
+        filterId = mFilterId;
+
+        // Check getId() too.
+        int32_t filterId32Bit;
+        status = mFilter->getId(&filterId32Bit);
+    }
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::getSharedAvMemoryHandle(int64_t filterId) {
+    EXPECT_TRUE(mFilters[filterId]) << "Open media filter first.";
+    NativeHandle avMemory;
+    int64_t avMemSize;
+    ndk::ScopedAStatus status = mFilters[filterId]->getAvSharedHandle(&avMemory, &avMemSize);
+    if (status.isOk()) {
+        mAvSharedHandle = android::dupFromAidl(avMemory);
+        mFilterCallbacks[mFilterId]->setSharedHandle(mAvSharedHandle);
+        mFilterCallbacks[mFilterId]->setMemSize(avMemSize);
+    }
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::releaseShareAvHandle(int64_t filterId) {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mFilters[filterId]) << "Open media filter first.";
+    EXPECT_TRUE(mAvSharedHandle) << "No shared av handle to release.";
+    status = mFilters[filterId]->releaseAvHandle(::android::makeToAidl(mAvSharedHandle),
+                                                 0 /*dataId*/);
+    native_handle_close(mAvSharedHandle);
+    native_handle_delete(mAvSharedHandle);
+    mAvSharedHandle = nullptr;
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, int64_t filterId) {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+    status = mFilters[filterId]->configure(setting);
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::configAvFilterStreamType(AvStreamType type, int64_t filterId) {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+
+    status = mFilters[filterId]->configureAvStreamType(type);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::configIpFilterCid(int32_t ipCid, int64_t filterId) {
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mFilters[filterId]) << "Open Ip filter first.";
+
+    status = mFilters[filterId]->configureIpCid(ipCid);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::getFilterMQDescriptor(int64_t filterId, bool getMqDesc) {
+    if (!getMqDesc) {
+        ALOGE("[vts] Filter does not need FMQ.");
+        return success();
+    }
+    ndk::ScopedAStatus status;
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+    EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
+
+    status = mFilters[filterId]->getQueueDesc(&mFilterMQDescriptor);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::startFilter(int64_t filterId) {
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+
+    ndk::ScopedAStatus status = mFilters[filterId]->start();
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::stopFilter(int64_t filterId) {
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+
+    ndk::ScopedAStatus status = mFilters[filterId]->stop();
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::closeFilter(int64_t filterId) {
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+    ndk::ScopedAStatus status = mFilters[filterId]->close();
+    if (status.isOk()) {
+        for (int i = 0; i < mUsedFilterIds.size(); i++) {
+            if (mUsedFilterIds[i] == filterId) {
+                mUsedFilterIds.erase(mUsedFilterIds.begin() + i);
+                break;
+            }
+        }
+        mFilterCallbacks.erase(filterId);
+        mFilters.erase(filterId);
+    }
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::configureMonitorEvent(int64_t filterId, int32_t monitorEventTypes) {
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+    ndk::ScopedAStatus status;
+
+    status = mFilters[filterId]->configureMonitorEvent(monitorEventTypes);
+    if (monitorEventTypes & static_cast<int32_t>(DemuxFilterMonitorEventType::SCRAMBLING_STATUS)) {
+        mFilterCallbacks[filterId]->testFilterScramblingEvent();
+    }
+    if (monitorEventTypes & static_cast<int32_t>(DemuxFilterMonitorEventType::IP_CID_CHANGE)) {
+        mFilterCallbacks[filterId]->testFilterIpCidEvent();
+    }
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::startIdTest(int64_t filterId) {
+    EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
+    mFilterCallbacks[filterId]->testStartIdAfterReconfigure();
+    return AssertionResult(true);
+}
+
+AssertionResult FilterTests::openTimeFilterInDemux() {
+    if (!mDemux) {
+        ALOGW("[vts] Test with openDemux first.");
+        return failure();
+    }
+
+    // Add time filter to the local demux
+    auto status = mDemux->openTimeFilter(&mTimeFilter);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::setTimeStamp(int64_t timeStamp) {
+    if (!mTimeFilter) {
+        ALOGW("[vts] Test with openTimeFilterInDemux first.");
+        return failure();
+    }
+
+    mBeginTimeStamp = timeStamp;
+    return AssertionResult(mTimeFilter->setTimeStamp(timeStamp).isOk());
+}
+
+AssertionResult FilterTests::getTimeStamp() {
+    if (!mTimeFilter) {
+        ALOGW("[vts] Test with openTimeFilterInDemux first.");
+        return failure();
+    }
+
+    int64_t timeStamp;
+    auto status = mTimeFilter->getTimeStamp(&timeStamp);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::setFilterDataSource(int64_t sourceFilterId, int64_t sinkFilterId) {
+    if (!mFilters[sourceFilterId] || !mFilters[sinkFilterId]) {
+        ALOGE("[vts] setFilterDataSource filter not opened.");
+        return failure();
+    }
+
+    auto status = mFilters[sinkFilterId]->setDataSource(mFilters[sourceFilterId]);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::setFilterDataSourceToDemux(int64_t filterId) {
+    if (!mFilters[filterId]) {
+        ALOGE("[vts] setFilterDataSourceToDemux filter not opened.");
+        return failure();
+    }
+
+    auto status = mFilters[filterId]->setDataSource(nullptr);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::clearTimeStamp() {
+    if (!mTimeFilter) {
+        ALOGW("[vts] Test with openTimeFilterInDemux first.");
+        return failure();
+    }
+
+    return AssertionResult(mTimeFilter->clearTimeStamp().isOk());
+}
+
+AssertionResult FilterTests::closeTimeFilter() {
+    if (!mTimeFilter) {
+        ALOGW("[vts] Test with openTimeFilterInDemux first.");
+        return failure();
+    }
+
+    return AssertionResult(mTimeFilter->close().isOk());
+}
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.h b/tv/tuner/aidl/vts/functional/FilterTests.h
new file mode 100644
index 0000000..f579441
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/FilterTests.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/BnFilterCallback.h>
+#include <aidl/android/hardware/tv/tuner/IDemux.h>
+#include <aidl/android/hardware/tv/tuner/IFilter.h>
+#include <aidl/android/hardware/tv/tuner/ITuner.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <future>
+#include <map>
+#include <unordered_map>
+
+#include <fmq/AidlMessageQueue.h>
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::Condition;
+using ::android::Mutex;
+using ::android::hardware::EventFlag;
+
+using ::testing::AssertionResult;
+
+using namespace aidl::android::hardware::tv::tuner;
+using namespace std;
+
+enum FilterEventType : uint8_t {
+    UNDEFINED,
+    SECTION,
+    MEDIA,
+    PES,
+    RECORD,
+    MMTPRECORD,
+    DOWNLOAD,
+    TEMI,
+};
+
+using FilterMQ = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+using MQDesc = MQDescriptor<int8_t, SynchronizedReadWrite>;
+
+#define WAIT_TIMEOUT 3000000000
+
+class FilterCallback : public BnFilterCallback {
+  public:
+    /**
+     * A FilterCallbackVerifier is used to test and verify filter callbacks.
+     * The function should return true when a callback has been handled by this
+     * filter verifier. This will cause the associated future to be unblocked.
+     * If the function returns false, we continue to wait for future callbacks
+     * (the future remains blocked).
+     */
+    using FilterCallbackVerifier = std::function<bool(const std::vector<DemuxFilterEvent>&)>;
+
+    virtual ::ndk::ScopedAStatus onFilterEvent(const vector<DemuxFilterEvent>& events) override;
+
+    std::future<void> verifyFilterCallback(FilterCallbackVerifier&& verifier);
+
+    virtual ::ndk::ScopedAStatus onFilterStatus(const DemuxFilterStatus /*status*/) override {
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    void setFilterId(int32_t filterId) { mFilterId = filterId; }
+    void setFilterInterface(std::shared_ptr<IFilter> filter) { mFilter = filter; }
+    void setSharedHandle(native_handle_t* sharedHandle) { mAvSharedHandle = sharedHandle; }
+    void setMemSize(uint64_t size) { mAvSharedMemSize = size; }
+
+    void testFilterDataOutput();
+    void testFilterScramblingEvent();
+    void testFilterIpCidEvent();
+    void testStartIdAfterReconfigure();
+
+    void readFilterEventsData(const vector<DemuxFilterEvent>& events);
+    bool dumpAvData(const DemuxFilterMediaEvent& event);
+
+  private:
+    int32_t mFilterId;
+    std::shared_ptr<IFilter> mFilter;
+
+    std::vector<std::pair<FilterCallbackVerifier, std::promise<void>>> mFilterCallbackVerifiers;
+    native_handle_t* mAvSharedHandle = nullptr;
+    uint64_t mAvSharedMemSize = -1;
+
+    android::Mutex mMsgLock;
+    android::Mutex mFilterOutputLock;
+    android::Condition mMsgCondition;
+
+    int mPidFilterOutputCount = 0;
+    int mScramblingStatusEvent = 0;
+    int mIpCidEvent = 0;
+    bool mStartIdReceived = false;
+};
+
+class FilterTests {
+  public:
+    void setService(std::shared_ptr<ITuner> tuner) { mService = tuner; }
+    void setDemux(std::shared_ptr<IDemux> demux) { mDemux = demux; }
+    std::shared_ptr<IFilter> getFilterById(int64_t filterId) { return mFilters[filterId]; }
+
+    map<int64_t, std::shared_ptr<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }
+
+    AssertionResult openFilterInDemux(DemuxFilterType type, int32_t bufferSize);
+    AssertionResult getNewlyOpenedFilterId_64bit(int64_t& filterId);
+    AssertionResult getSharedAvMemoryHandle(int64_t filterId);
+    AssertionResult releaseShareAvHandle(int64_t filterId);
+    AssertionResult configFilter(DemuxFilterSettings setting, int64_t filterId);
+    AssertionResult configAvFilterStreamType(AvStreamType type, int64_t filterId);
+    AssertionResult configIpFilterCid(int32_t ipCid, int64_t filterId);
+    AssertionResult configureMonitorEvent(int64_t filterId, int32_t monitorEventTypes);
+    AssertionResult getFilterMQDescriptor(int64_t filterId, bool getMqDesc);
+    AssertionResult startFilter(int64_t filterId);
+    AssertionResult stopFilter(int64_t filterId);
+    AssertionResult closeFilter(int64_t filterId);
+    AssertionResult startIdTest(int64_t filterId);
+
+    AssertionResult openTimeFilterInDemux();
+    AssertionResult setTimeStamp(int64_t timeStamp);
+    AssertionResult getTimeStamp();
+    AssertionResult setFilterDataSource(int64_t sourceFilterId, int64_t sinkFilterId);
+    AssertionResult setFilterDataSourceToDemux(int64_t filterId);
+    AssertionResult clearTimeStamp();
+    AssertionResult closeTimeFilter();
+
+  protected:
+    static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+    static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+    std::shared_ptr<ITuner> mService;
+    std::shared_ptr<IFilter> mFilter;
+    std::shared_ptr<IDemux> mDemux;
+    std::shared_ptr<ITimeFilter> mTimeFilter;
+    map<int64_t, std::shared_ptr<IFilter>> mFilters;
+    map<int64_t, std::shared_ptr<FilterCallback>> mFilterCallbacks;
+
+    std::shared_ptr<FilterCallback> mFilterCallback;
+    MQDesc mFilterMQDescriptor;
+    vector<int64_t> mUsedFilterIds;
+
+    native_handle_t* mAvSharedHandle = nullptr;
+    int64_t mFilterId = -1;
+    int64_t mBeginTimeStamp;
+};
diff --git a/tv/tuner/aidl/vts/functional/FrontendTests.cpp b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
new file mode 100644
index 0000000..075ffad
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
@@ -0,0 +1,531 @@
+/*
+ * 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.
+ */
+
+#include "FrontendTests.h"
+
+ndk::ScopedAStatus FrontendCallback::onEvent(FrontendEventType frontendEventType) {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    ALOGD("[vts] frontend event received. Type: %d", frontendEventType);
+    mEventReceived = true;
+    mMsgCondition.signal();
+    switch (frontendEventType) {
+        case FrontendEventType::LOCKED:
+            mLockMsgReceived = true;
+            mLockMsgCondition.signal();
+            break;
+        default:
+            // do nothing
+            break;
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus FrontendCallback::onScanMessage(FrontendScanMessageType type,
+                                                   const FrontendScanMessage& message) {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    while (!mScanMsgProcessed) {
+        mMsgCondition.wait(mMsgLock);
+    }
+    ALOGD("[vts] frontend scan message. Type: %d", type);
+    switch (message.getTag()) {
+        case FrontendScanMessage::modulation:
+            readFrontendScanMessage_Modulation(message.get<FrontendScanMessage::Tag::modulation>());
+            break;
+        case FrontendScanMessage::Tag::isHighPriority:
+            ALOGD("[vts] frontend scan message high priority: %d",
+                  message.get<FrontendScanMessage::Tag::isHighPriority>());
+            break;
+        case FrontendScanMessage::Tag::annex:
+            ALOGD("[vts] frontend scan message dvbc annex: %hhu",
+                  message.get<FrontendScanMessage::Tag::annex>());
+            break;
+        default:
+            break;
+    }
+    mScanMessageReceived = true;
+    mScanMsgProcessed = false;
+    mScanMessageType = type;
+    mScanMessage = message;
+    mMsgCondition.signal();
+    return ndk::ScopedAStatus::ok();
+}
+
+void FrontendCallback::readFrontendScanMessage_Modulation(FrontendModulation modulation) {
+    switch (modulation.getTag()) {
+        case FrontendModulation::Tag::dvbc:
+            ALOGD("[vts] frontend scan message modulation dvbc: %d",
+                  modulation.get<FrontendModulation::Tag::dvbc>());
+            break;
+        case FrontendModulation::Tag::dvbs:
+            ALOGD("[vts] frontend scan message modulation dvbs: %d",
+                  modulation.get<FrontendModulation::Tag::dvbs>());
+            break;
+        case FrontendModulation::Tag::isdbs:
+            ALOGD("[vts] frontend scan message modulation isdbs: %d",
+                  modulation.get<FrontendModulation::Tag::isdbs>());
+            break;
+        case FrontendModulation::Tag::isdbs3:
+            ALOGD("[vts] frontend scan message modulation isdbs3: %d",
+                  modulation.get<FrontendModulation::Tag::isdbs3>());
+            break;
+        case FrontendModulation::Tag::isdbt:
+            ALOGD("[vts] frontend scan message modulation isdbt: %d",
+                  modulation.get<FrontendModulation::Tag::isdbt>());
+            break;
+        case FrontendModulation::Tag::atsc:
+            ALOGD("[vts] frontend scan message modulation atsc: %d",
+                  modulation.get<FrontendModulation::Tag::atsc>());
+            break;
+        case FrontendModulation::Tag::atsc3:
+            ALOGD("[vts] frontend scan message modulation atsc3: %d",
+                  modulation.get<FrontendModulation::Tag::atsc3>());
+            break;
+        case FrontendModulation::Tag::dvbt:
+            ALOGD("[vts] frontend scan message modulation dvbt: %d",
+                  modulation.get<FrontendModulation::Tag::dvbt>());
+            break;
+        default:
+            break;
+    }
+}
+
+void FrontendCallback::tuneTestOnLock(std::shared_ptr<IFrontend>& frontend,
+                                      FrontendSettings settings) {
+    ndk::ScopedAStatus result = frontend->tune(settings);
+    EXPECT_TRUE(result.isOk());
+
+    android::Mutex::Autolock autoLock(mMsgLock);
+    while (!mLockMsgReceived) {
+        if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+            EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
+            mLockMsgReceived = false;
+            return;
+        }
+    }
+    mLockMsgReceived = false;
+}
+
+void FrontendCallback::scanTest(std::shared_ptr<IFrontend>& frontend, FrontendConfig config,
+                                FrontendScanType type) {
+    int64_t targetFrequency = getTargetFrequency(config.settings);
+    if (type == FrontendScanType::SCAN_BLIND) {
+        // reset the frequency in the scan configuration to test blind scan. The settings param of
+        // passed in means the real input config on the transponder connected to the DUT.
+        // We want the blind the test to start from lower frequency than this to check the blind
+        // scan implementation.
+        resetBlindScanStartingFrequency(config, targetFrequency - 100 * 1000);
+    }
+
+    ndk::ScopedAStatus result = frontend->scan(config.settings, type);
+    EXPECT_TRUE(result.isOk());
+
+    bool scanMsgLockedReceived = false;
+    bool targetFrequencyReceived = false;
+
+    android::Mutex::Autolock autoLock(mMsgLock);
+wait:
+    while (!mScanMessageReceived) {
+        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+            EXPECT_TRUE(false) << "Scan message not received within timeout";
+            mScanMessageReceived = false;
+            mScanMsgProcessed = true;
+            return;
+        }
+    }
+
+    if (mScanMessageType != FrontendScanMessageType::END) {
+        if (mScanMessageType == FrontendScanMessageType::LOCKED) {
+            scanMsgLockedReceived = true;
+            result = frontend->scan(config.settings, type);
+            EXPECT_TRUE(result.isOk());
+        }
+
+        if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
+            targetFrequencyReceived =
+                    mScanMessage.get<FrontendScanMessage::Tag::frequencies>().size() > 0 &&
+                    mScanMessage.get<FrontendScanMessage::Tag::frequencies>()[0] == targetFrequency;
+        }
+
+        if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
+            ALOGD("[vts] Scan in progress...[%d%%]",
+                  mScanMessage.get<FrontendScanMessage::Tag::progressPercent>());
+        }
+
+        mScanMessageReceived = false;
+        mScanMsgProcessed = true;
+        mMsgCondition.signal();
+        goto wait;
+    }
+
+    EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
+    if (type == FrontendScanType::SCAN_BLIND)
+        EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
+    mScanMessageReceived = false;
+    mScanMsgProcessed = true;
+}
+
+int64_t FrontendCallback::getTargetFrequency(FrontendSettings& settings) {
+    switch (settings.getTag()) {
+        case FrontendSettings::Tag::analog:
+            return settings.get<FrontendSettings::Tag::analog>().frequency;
+        case FrontendSettings::Tag::atsc:
+            return settings.get<FrontendSettings::Tag::atsc>().frequency;
+        case FrontendSettings::Tag::atsc3:
+            return settings.get<FrontendSettings::Tag::atsc3>().frequency;
+        case FrontendSettings::Tag::dvbc:
+            return settings.get<FrontendSettings::Tag::dvbc>().frequency;
+        case FrontendSettings::Tag::dvbs:
+            return settings.get<FrontendSettings::Tag::dvbs>().frequency;
+        case FrontendSettings::Tag::dvbt:
+            return settings.get<FrontendSettings::Tag::dvbt>().frequency;
+        case FrontendSettings::Tag::isdbs:
+            return settings.get<FrontendSettings::Tag::isdbs>().frequency;
+        case FrontendSettings::Tag::isdbs3:
+            return settings.get<FrontendSettings::Tag::isdbs3>().frequency;
+        case FrontendSettings::Tag::isdbt:
+            return settings.get<FrontendSettings::Tag::isdbt>().frequency;
+        default:
+            return 0;
+    }
+}
+
+void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig& config,
+                                                       int64_t resetingFreq) {
+    switch (config.settings.getTag()) {
+        case FrontendSettings::Tag::analog:
+            config.settings.get<FrontendSettings::Tag::analog>().frequency = resetingFreq;
+            break;
+        case FrontendSettings::Tag::atsc:
+            config.settings.get<FrontendSettings::Tag::atsc>().frequency = resetingFreq;
+            break;
+        case FrontendSettings::Tag::atsc3:
+            config.settings.get<FrontendSettings::Tag::atsc3>().frequency = resetingFreq;
+            break;
+        case FrontendSettings::Tag::dvbc:
+            config.settings.get<FrontendSettings::Tag::dvbc>().frequency = resetingFreq;
+            break;
+        case FrontendSettings::Tag::dvbs:
+            config.settings.get<FrontendSettings::Tag::dvbs>().frequency = resetingFreq;
+            break;
+        case FrontendSettings::Tag::dvbt:
+            config.settings.get<FrontendSettings::Tag::dvbt>().frequency = resetingFreq;
+            break;
+        case FrontendSettings::Tag::isdbs:
+            config.settings.get<FrontendSettings::Tag::isdbs>().frequency = resetingFreq;
+            break;
+        case FrontendSettings::Tag::isdbs3:
+            config.settings.get<FrontendSettings::Tag::isdbs3>().frequency = resetingFreq;
+            break;
+        case FrontendSettings::Tag::isdbt:
+            config.settings.get<FrontendSettings::Tag::isdbt>().frequency = resetingFreq;
+            break;
+        default:
+            break;
+    }
+}
+
+AssertionResult FrontendTests::getFrontendIds() {
+    ndk::ScopedAStatus status;
+    status = mService->getFrontendIds(&mFeIds);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FrontendTests::getFrontendInfo(int32_t frontendId) {
+    ndk::ScopedAStatus status;
+    status = mService->getFrontendInfo(frontendId, &mFrontendInfo);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FrontendTests::openFrontendById(int32_t frontendId) {
+    ndk::ScopedAStatus status;
+    status = mService->openFrontendById(frontendId, &mFrontend);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FrontendTests::setFrontendCallback() {
+    EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+    mFrontendCallback = ndk::SharedRefBase::make<FrontendCallback>();
+    auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
+    return AssertionResult(callbackStatus.isOk());
+}
+
+AssertionResult FrontendTests::scanFrontend(FrontendConfig config, FrontendScanType type) {
+    EXPECT_TRUE(mFrontendCallback)
+            << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
+
+    EXPECT_TRUE(mFrontendInfo.type == config.type)
+            << "FrontendConfig does not match the frontend info of the given id.";
+
+    mFrontendCallback->scanTest(mFrontend, config, type);
+    return AssertionResult(true);
+}
+
+AssertionResult FrontendTests::stopScanFrontend() {
+    EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+    ndk::ScopedAStatus status;
+    status = mFrontend->stopScan();
+
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FrontendTests::setLnb(int32_t lnbId) {
+    if (!mFrontendCallback) {
+        ALOGW("[vts] open and set frontend callback first.");
+        return failure();
+    }
+    return AssertionResult(mFrontend->setLnb(lnbId).isOk());
+}
+
+AssertionResult FrontendTests::linkCiCam(int32_t ciCamId) {
+    ndk::ScopedAStatus status;
+    int32_t ltsId;
+    status = mFrontend->linkCiCam(ciCamId, &ltsId);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FrontendTests::unlinkCiCam(int32_t ciCamId) {
+    ndk::ScopedAStatus status = mFrontend->unlinkCiCam(ciCamId);
+    return AssertionResult(status.isOk());
+}
+
+void FrontendTests::verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
+                                         vector<FrontendStatus> expectStatuses) {
+    ASSERT_TRUE(mFrontend) << "Frontend is not opened yet.";
+    ndk::ScopedAStatus status;
+    vector<FrontendStatus> realStatuses;
+
+    status = mFrontend->getStatus(statusTypes, &realStatuses);
+    ASSERT_TRUE(status.isOk() && realStatuses.size() == statusTypes.size());
+
+    for (int i = 0; i < statusTypes.size(); i++) {
+        FrontendStatusType type = statusTypes[i];
+        switch (type) {
+            case FrontendStatusType::MODULATIONS: {
+                // TODO: verify modulations
+                break;
+            }
+            case FrontendStatusType::BERS: {
+                ASSERT_TRUE(std::equal(realStatuses[i].get<FrontendStatus::Tag::bers>().begin(),
+                                       realStatuses[i].get<FrontendStatus::Tag::bers>().end(),
+                                       expectStatuses[i].get<FrontendStatus::Tag::bers>().begin()));
+                break;
+            }
+            case FrontendStatusType::CODERATES: {
+                ASSERT_TRUE(std::equal(
+                        realStatuses[i].get<FrontendStatus::Tag::codeRates>().begin(),
+                        realStatuses[i].get<FrontendStatus::Tag::codeRates>().end(),
+                        expectStatuses[i].get<FrontendStatus::Tag::codeRates>().begin()));
+                break;
+            }
+            case FrontendStatusType::GUARD_INTERVAL: {
+                // TODO: verify interval
+                break;
+            }
+            case FrontendStatusType::TRANSMISSION_MODE: {
+                // TODO: verify tranmission mode
+                break;
+            }
+            case FrontendStatusType::UEC: {
+                ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::uec>() ==
+                            expectStatuses[i].get<FrontendStatus::Tag::uec>());
+                break;
+            }
+            case FrontendStatusType::T2_SYSTEM_ID: {
+                ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::systemId>() ==
+                            expectStatuses[i].get<FrontendStatus::Tag::systemId>());
+                break;
+            }
+            case FrontendStatusType::INTERLEAVINGS: {
+                ASSERT_TRUE(std::equal(
+                        realStatuses[i].get<FrontendStatus::Tag::interleaving>().begin(),
+                        realStatuses[i].get<FrontendStatus::Tag::interleaving>().end(),
+                        expectStatuses[i].get<FrontendStatus::Tag::interleaving>().begin()));
+                break;
+            }
+            case FrontendStatusType::ISDBT_SEGMENTS: {
+                ASSERT_TRUE(std::equal(
+                        realStatuses[i].get<FrontendStatus::Tag::isdbtSegment>().begin(),
+                        realStatuses[i].get<FrontendStatus::Tag::isdbtSegment>().end(),
+                        expectStatuses[i].get<FrontendStatus::Tag::isdbtSegment>().begin()));
+                break;
+            }
+            case FrontendStatusType::TS_DATA_RATES: {
+                ASSERT_TRUE(std::equal(
+                        realStatuses[i].get<FrontendStatus::Tag::tsDataRate>().begin(),
+                        realStatuses[i].get<FrontendStatus::Tag::tsDataRate>().end(),
+                        expectStatuses[i].get<FrontendStatus::Tag::tsDataRate>().begin()));
+                break;
+            }
+            case FrontendStatusType::ROLL_OFF: {
+                // TODO: verify roll off
+                break;
+            }
+            case FrontendStatusType::IS_MISO: {
+                ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::isMiso>() ==
+                            expectStatuses[i].get<FrontendStatus::Tag::isMiso>());
+                break;
+            }
+            case FrontendStatusType::IS_LINEAR: {
+                ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::isLinear>() ==
+                            expectStatuses[i].get<FrontendStatus::Tag::isLinear>());
+                break;
+            }
+            case FrontendStatusType::IS_SHORT_FRAMES: {
+                ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::isShortFrames>() ==
+                            expectStatuses[i].get<FrontendStatus::Tag::isShortFrames>());
+                break;
+            }
+            case FrontendStatusType::ISDBT_MODE: {
+                ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::isdbtMode>() ==
+                            expectStatuses[i].get<FrontendStatus::Tag::isdbtMode>());
+                break;
+            }
+            case FrontendStatusType::ISDBT_PARTIAL_RECEPTION_FLAG: {
+                ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::partialReceptionFlag>() ==
+                            expectStatuses[i].get<FrontendStatus::Tag::partialReceptionFlag>());
+                break;
+            }
+            case FrontendStatusType::STREAM_ID_LIST: {
+                ASSERT_TRUE(std::equal(
+                        realStatuses[i].get<FrontendStatus::Tag::streamIdList>().begin(),
+                        realStatuses[i].get<FrontendStatus::Tag::streamIdList>().end(),
+                        expectStatuses[i].get<FrontendStatus::Tag::streamIdList>().begin()));
+                break;
+            }
+            case FrontendStatusType::DVBT_CELL_IDS: {
+                ASSERT_TRUE(std::equal(
+                        realStatuses[i].get<FrontendStatus::Tag::dvbtCellIds>().begin(),
+                        realStatuses[i].get<FrontendStatus::Tag::dvbtCellIds>().end(),
+                        expectStatuses[i].get<FrontendStatus::Tag::dvbtCellIds>().begin()));
+                break;
+            }
+            default: {
+                continue;
+            }
+        }
+    }
+    ASSERT_TRUE(status.isOk());
+}
+
+AssertionResult FrontendTests::tuneFrontend(FrontendConfig config, bool testWithDemux) {
+    EXPECT_TRUE(mFrontendCallback)
+            << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
+
+    EXPECT_TRUE(mFrontendInfo.type == config.type)
+            << "FrontendConfig does not match the frontend info of the given id.";
+
+    mIsSoftwareFe = config.isSoftwareFe;
+    if (mIsSoftwareFe && testWithDemux) {
+        if (getDvrTests()->openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) != success()) {
+            ALOGW("[vts] Software frontend dvr configure openDvr failed.");
+            return failure();
+        }
+        if (getDvrTests()->configDvrPlayback(mDvrConfig.settings) != success()) {
+            ALOGW("[vts] Software frontend dvr configure Dvr playback failed.");
+            return failure();
+        }
+        if (getDvrTests()->getDvrPlaybackMQDescriptor() != success()) {
+            ALOGW("[vts] Software frontend dvr configure get MQDesc failed.");
+            return failure();
+        }
+        getDvrTests()->startPlaybackInputThread(
+                mDvrConfig.playbackInputFile,
+                mDvrConfig.settings.get<DvrSettings::Tag::playback>());
+        getDvrTests()->startDvrPlayback();
+    }
+    mFrontendCallback->tuneTestOnLock(mFrontend, config.settings);
+    return AssertionResult(true);
+}
+
+AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) {
+    EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+    ndk::ScopedAStatus status;
+    status = mFrontend->stopTune();
+    if (mIsSoftwareFe && testWithDemux) {
+        getDvrTests()->stopPlaybackThread();
+        getDvrTests()->stopDvrPlayback();
+        getDvrTests()->closeDvrPlayback();
+    }
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FrontendTests::closeFrontend() {
+    EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+    ndk::ScopedAStatus status;
+    status = mFrontend->close();
+    mFrontend = nullptr;
+    mFrontendCallback = nullptr;
+    return AssertionResult(status.isOk());
+}
+
+void FrontendTests::getFrontendIdByType(FrontendType feType, int32_t& feId) {
+    ASSERT_TRUE(getFrontendIds());
+    for (size_t i = 0; i < mFeIds.size(); i++) {
+        ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
+        if (mFrontendInfo.type != feType) {
+            continue;
+        }
+        feId = mFeIds[i];
+        return;
+    }
+    feId = INVALID_ID;
+}
+
+AssertionResult FrontendTests::verifyHardwareInfo() {
+    EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+    std::string info;
+    ndk::ScopedAStatus status = mFrontend->getHardwareInfo(&info);
+    return AssertionResult(status.isOk() && !info.empty());
+}
+
+void FrontendTests::tuneTest(FrontendConfig frontendConf) {
+    int32_t feId;
+    getFrontendIdByType(frontendConf.type, feId);
+    ASSERT_TRUE(feId != INVALID_ID);
+    ASSERT_TRUE(openFrontendById(feId));
+    ASSERT_TRUE(setFrontendCallback());
+    if (frontendConf.canConnectToCiCam) {
+        ASSERT_TRUE(linkCiCam(frontendConf.ciCamId));
+        ASSERT_TRUE(unlinkCiCam(frontendConf.ciCamId));
+    }
+    ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
+    verifyFrontendStatus(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
+    ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
+    ASSERT_TRUE(closeFrontend());
+}
+
+void FrontendTests::debugInfoTest(FrontendConfig frontendConf) {
+    int32_t feId;
+    getFrontendIdByType(frontendConf.type, feId);
+    ASSERT_TRUE(feId != INVALID_ID);
+    ASSERT_TRUE(openFrontendById(feId));
+    ASSERT_TRUE(setFrontendCallback());
+    ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
+    ASSERT_TRUE(verifyHardwareInfo());
+    ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
+    ASSERT_TRUE(closeFrontend());
+}
+
+void FrontendTests::scanTest(FrontendConfig frontendConf, FrontendScanType scanType) {
+    int32_t feId;
+    getFrontendIdByType(frontendConf.type, feId);
+    ASSERT_TRUE(feId != INVALID_ID);
+    ASSERT_TRUE(openFrontendById(feId));
+    ASSERT_TRUE(setFrontendCallback());
+    ASSERT_TRUE(scanFrontend(frontendConf, scanType));
+    ASSERT_TRUE(stopScanFrontend());
+    ASSERT_TRUE(closeFrontend());
+}
diff --git a/tv/tuner/aidl/vts/functional/FrontendTests.h b/tv/tuner/aidl/vts/functional/FrontendTests.h
new file mode 100644
index 0000000..8f769a0
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/BnFrontendCallback.h>
+#include <aidl/android/hardware/tv/tuner/IFrontend.h>
+#include <aidl/android/hardware/tv/tuner/ITuner.h>
+
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+
+#include "DvrTests.h"
+#include "VtsHalTvTunerTestConfigurations.h"
+
+#define WAIT_TIMEOUT 3000000000
+#define INVALID_ID -1
+
+using android::Condition;
+using android::Mutex;
+
+using ::testing::AssertionResult;
+
+using namespace aidl::android::hardware::tv::tuner;
+using namespace std;
+
+#define INVALID_ID -1
+#define WAIT_TIMEOUT 3000000000
+
+class FrontendCallback : public BnFrontendCallback {
+  public:
+    virtual ndk::ScopedAStatus onEvent(FrontendEventType frontendEventType) override;
+    virtual ndk::ScopedAStatus onScanMessage(FrontendScanMessageType type,
+                                             const FrontendScanMessage& message) override;
+
+    void tuneTestOnLock(std::shared_ptr<IFrontend>& frontend, FrontendSettings settings);
+    void scanTest(std::shared_ptr<IFrontend>& frontend, FrontendConfig config,
+                  FrontendScanType type);
+
+    // Helper methods
+    int64_t getTargetFrequency(FrontendSettings& settings);
+    void resetBlindScanStartingFrequency(FrontendConfig& config, int64_t resetingFreq);
+
+  private:
+    void readFrontendScanMessage_Modulation(FrontendModulation modulation);
+
+    bool mEventReceived = false;
+    bool mScanMessageReceived = false;
+    bool mLockMsgReceived = false;
+    bool mScanMsgProcessed = true;
+    FrontendScanMessageType mScanMessageType;
+    FrontendScanMessage mScanMessage;
+    vector<int8_t> mEventMessage;
+    android::Mutex mMsgLock;
+    android::Condition mMsgCondition;
+    android::Condition mLockMsgCondition;
+};
+
+class FrontendTests {
+  public:
+    void setService(std::shared_ptr<ITuner> tuner) {
+        mService = tuner;
+        getDvrTests()->setService(tuner);
+        getDefaultSoftwareFrontendPlaybackConfig(mDvrConfig);
+    }
+
+    AssertionResult getFrontendIds();
+    AssertionResult getFrontendInfo(int32_t frontendId);
+    AssertionResult openFrontendById(int32_t frontendId);
+    AssertionResult setFrontendCallback();
+    AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
+    AssertionResult stopScanFrontend();
+    AssertionResult setLnb(int32_t lnbId);
+    AssertionResult tuneFrontend(FrontendConfig config, bool testWithDemux);
+    void verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
+                              vector<FrontendStatus> expectStatuses);
+    AssertionResult stopTuneFrontend(bool testWithDemux);
+    AssertionResult closeFrontend();
+
+    AssertionResult linkCiCam(int32_t ciCamId);
+    AssertionResult unlinkCiCam(int32_t ciCamId);
+    AssertionResult verifyHardwareInfo();
+
+    void getFrontendIdByType(FrontendType feType, int32_t& feId);
+    void tuneTest(FrontendConfig frontendConf);
+    void scanTest(FrontendConfig frontend, FrontendScanType type);
+    void debugInfoTest(FrontendConfig frontendConf);
+
+    void setDvrTests(DvrTests* dvrTests) { mExternalDvrTests = dvrTests; }
+    void setDemux(std::shared_ptr<IDemux> demux) { getDvrTests()->setDemux(demux); }
+    void setSoftwareFrontendDvrConfig(DvrConfig conf) { mDvrConfig = conf; }
+
+  protected:
+    static AssertionResult failure() { return ::testing::AssertionFailure(); }
+    static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+    void getDefaultSoftwareFrontendPlaybackConfig(DvrConfig& dvrConfig) {
+        PlaybackSettings playbackSettings{
+                .statusMask = 0xf,
+                .lowThreshold = 0x1000,
+                .highThreshold = 0x07fff,
+                .dataFormat = DataFormat::ES,
+                .packetSize = static_cast<int64_t>(188),
+        };
+        dvrConfig.type = DvrType::PLAYBACK;
+        dvrConfig.playbackInputFile = "/data/local/tmp/test.es";
+        dvrConfig.bufferSize = FMQ_SIZE_4M;
+        dvrConfig.settings.set<DvrSettings::playback>(playbackSettings);
+    }
+
+    DvrTests* getDvrTests() {
+        return (mExternalDvrTests != nullptr ? mExternalDvrTests : &mDvrTests);
+    }
+
+    std::shared_ptr<ITuner> mService;
+    std::shared_ptr<IFrontend> mFrontend;
+    FrontendInfo mFrontendInfo;
+    std::shared_ptr<FrontendCallback> mFrontendCallback;
+    vector<int32_t> mFeIds;
+
+    DvrTests mDvrTests;
+    DvrTests* mExternalDvrTests = nullptr;
+    bool mIsSoftwareFe = false;
+    DvrConfig mDvrConfig;
+};
diff --git a/tv/tuner/aidl/vts/functional/LnbTests.cpp b/tv/tuner/aidl/vts/functional/LnbTests.cpp
new file mode 100644
index 0000000..d62e58a
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/LnbTests.cpp
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+#include <log/log.h>
+
+#include "LnbTests.h"
+
+ndk::ScopedAStatus LnbCallback::onEvent(LnbEventType lnbEventType) {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    ALOGD("[vts] lnb event received. Type: %d", lnbEventType);
+    mEventReceived = true;
+    mMsgCondition.signal();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus LnbCallback::onDiseqcMessage(const vector<uint8_t>& diseqcMessage) {
+    string msg(diseqcMessage.begin(), diseqcMessage.end());
+    ALOGD("[vts] onDiseqcMessage %s", msg.c_str());
+    return ndk::ScopedAStatus::ok();
+}
+
+AssertionResult LnbTests::getLnbIds(vector<int32_t>& ids) {
+    ndk::ScopedAStatus status;
+    status = mService->getLnbIds(&ids);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult LnbTests::openLnbById(int32_t lnbId) {
+    ndk::ScopedAStatus status;
+    status = mService->openLnbById(lnbId, &mLnb);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult LnbTests::openLnbByName(string lnbName, int32_t& id) {
+    ndk::ScopedAStatus status;
+    vector<int32_t> ids;
+    status = mService->openLnbByName(lnbName, &ids, &mLnb);
+    if (status.isOk()) {
+        id = ids[0];
+    }
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult LnbTests::setLnbCallback() {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    mLnbCallback = ndk::SharedRefBase::make<LnbCallback>();
+    auto callbackStatus = mLnb->setCallback(mLnbCallback);
+    return AssertionResult(callbackStatus.isOk());
+}
+
+AssertionResult LnbTests::setVoltage(LnbVoltage voltage) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    ndk::ScopedAStatus status = mLnb->setVoltage(voltage);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult LnbTests::setTone(LnbTone tone) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    ndk::ScopedAStatus status = mLnb->setTone(tone);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult LnbTests::setSatellitePosition(LnbPosition position) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    ndk::ScopedAStatus status = mLnb->setSatellitePosition(position);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult LnbTests::sendDiseqcMessage(vector<uint8_t> diseqcMsg) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    ndk::ScopedAStatus status = mLnb->sendDiseqcMessage(diseqcMsg);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult LnbTests::closeLnb() {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    ndk::ScopedAStatus status = mLnb->close();
+    mLnb = nullptr;
+    mLnbCallback = nullptr;
+    return AssertionResult(status.isOk());
+}
diff --git a/tv/tuner/aidl/vts/functional/LnbTests.h b/tv/tuner/aidl/vts/functional/LnbTests.h
new file mode 100644
index 0000000..d6b5a25
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/LnbTests.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tv/tuner/BnLnbCallback.h>
+#include <aidl/android/hardware/tv/tuner/ILnb.h>
+#include <aidl/android/hardware/tv/tuner/ITuner.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+using android::Condition;
+using android::Mutex;
+
+using ::testing::AssertionResult;
+
+using namespace aidl::android::hardware::tv::tuner;
+using namespace std;
+
+class LnbCallback : public BnLnbCallback {
+  public:
+    virtual ::ndk::ScopedAStatus onEvent(LnbEventType lnbEventType) override;
+    virtual ::ndk::ScopedAStatus onDiseqcMessage(
+            const std::vector<uint8_t>& diseqcMessage) override;
+
+  private:
+    bool mEventReceived = false;
+    android::Mutex mMsgLock;
+    android::Condition mMsgCondition;
+};
+
+class LnbTests {
+  public:
+    void setService(std::shared_ptr<ITuner> tuner) { mService = tuner; }
+
+    AssertionResult getLnbIds(vector<int32_t>& ids);
+    AssertionResult openLnbById(int32_t lnbId);
+    AssertionResult openLnbByName(string lnbName, int32_t& lnbId);
+    AssertionResult setLnbCallback();
+    AssertionResult setVoltage(LnbVoltage voltage);
+    AssertionResult setTone(LnbTone tone);
+    AssertionResult setSatellitePosition(LnbPosition position);
+    AssertionResult sendDiseqcMessage(vector<uint8_t> diseqcMsg);
+    AssertionResult closeLnb();
+
+  protected:
+    static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+    static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+    std::shared_ptr<ITuner> mService;
+    std::shared_ptr<ILnb> mLnb;
+    std::shared_ptr<LnbCallback> mLnbCallback;
+    vector<int32_t> mLnbIds;
+};
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
new file mode 100644
index 0000000..f489bf7
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -0,0 +1,1033 @@
+/*
+ * 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.
+ */
+
+#include "VtsHalTvTunerTargetTest.h"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+namespace {
+
+AssertionResult TunerBroadcastAidlTest::filterDataOutputTest() {
+    return filterDataOutputTestBase(mFilterTests);
+}
+
+AssertionResult TunerPlaybackAidlTest::filterDataOutputTest() {
+    return filterDataOutputTestBase(mFilterTests);
+}
+
+AssertionResult TunerDescramblerAidlTest::filterDataOutputTest() {
+    return filterDataOutputTestBase(mFilterTests);
+}
+
+void TunerFilterAidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf,
+                                                        FrontendConfig frontendConf) {
+    int32_t feId;
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    int64_t filterId;
+
+    mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+    ASSERT_TRUE(feId != INVALID_ID);
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    mFilterTests.setDemux(demux);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+    if (filterConf.type.mainType == DemuxFilterMainType::IP) {
+        ASSERT_TRUE(mFilterTests.configIpFilterCid(filterConf.ipCid, filterId));
+    }
+    if (filterConf.monitorEventTypes > 0) {
+        ASSERT_TRUE(mFilterTests.configureMonitorEvent(filterId, filterConf.monitorEventTypes));
+    }
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+void TunerFilterAidlTest::reconfigSingleFilterInDemuxTest(FilterConfig filterConf,
+                                                          FilterConfig filterReconf,
+                                                          FrontendConfig frontendConf) {
+    int32_t feId;
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    int64_t filterId;
+
+    mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+    ASSERT_TRUE(feId != INVALID_ID);
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    if (frontendConf.isSoftwareFe) {
+        mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[live.dvrSoftwareFeId]);
+    }
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    mFrontendTests.setDemux(demux);
+    mFilterTests.setDemux(demux);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterReconf.settings, filterId));
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+    ASSERT_TRUE(mFilterTests.startIdTest(filterId));
+    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
+    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+void TunerFilterAidlTest::testTimeFilter(TimeFilterConfig filterConf) {
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    DemuxCapabilities caps;
+
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.getDemuxCaps(caps));
+    ASSERT_TRUE(caps.bTimeFilter);
+    mFilterTests.setDemux(demux);
+    ASSERT_TRUE(mFilterTests.openTimeFilterInDemux());
+    ASSERT_TRUE(mFilterTests.setTimeStamp(filterConf.timeStamp));
+    ASSERT_TRUE(mFilterTests.getTimeStamp());
+    ASSERT_TRUE(mFilterTests.clearTimeStamp());
+    ASSERT_TRUE(mFilterTests.closeTimeFilter());
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
+void TunerBroadcastAidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
+                                                       FrontendConfig frontendConf) {
+    int32_t feId;
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    int64_t filterId;
+
+    mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    if (mLnbId) {
+        ASSERT_TRUE(mFrontendTests.setLnb(*mLnbId));
+    }
+    if (frontendConf.isSoftwareFe) {
+        mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[live.dvrSoftwareFeId]);
+    }
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    mFrontendTests.setDemux(demux);
+    mFilterTests.setDemux(demux);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    // tune test
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+    ASSERT_TRUE(filterDataOutputTest());
+    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
+    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+void TunerBroadcastAidlTest::broadcastSingleFilterTestWithLnb(FilterConfig filterConf,
+                                                              FrontendConfig frontendConf,
+                                                              LnbConfig lnbConf) {
+    if (lnbConf.name.compare(emptyHardwareId) == 0) {
+        vector<int32_t> ids;
+        ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+        ASSERT_TRUE(ids.size() > 0);
+        ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+        mLnbId = &ids[0];
+    } else {
+        mLnbId = (int32_t*)malloc(sizeof(int32_t));
+        ASSERT_TRUE(mLnbTests.openLnbByName(lnbConf.name, *mLnbId));
+    }
+    ASSERT_TRUE(mLnbTests.setLnbCallback());
+    ASSERT_TRUE(mLnbTests.setVoltage(lnbConf.voltage));
+    ASSERT_TRUE(mLnbTests.setTone(lnbConf.tone));
+    ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbConf.position));
+    broadcastSingleFilterTest(filterConf, frontendConf);
+    ASSERT_TRUE(mLnbTests.closeLnb());
+    mLnbId = nullptr;
+}
+
+void TunerBroadcastAidlTest::mediaFilterUsingSharedMemoryTest(FilterConfig filterConf,
+                                                              FrontendConfig frontendConf) {
+    int32_t feId;
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    int64_t filterId;
+
+    mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+    ASSERT_TRUE(feId != INVALID_ID);
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    if (frontendConf.isSoftwareFe) {
+        mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[live.dvrSoftwareFeId]);
+    }
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    mFrontendTests.setDemux(demux);
+    mFilterTests.setDemux(demux);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+    ASSERT_TRUE(mFilterTests.getSharedAvMemoryHandle(filterId));
+    ASSERT_TRUE(mFilterTests.configAvFilterStreamType(filterConf.streamType, filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    // tune test
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+    ASSERT_TRUE(filterDataOutputTest());
+    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
+    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    ASSERT_TRUE(mFilterTests.releaseShareAvHandle(filterId));
+    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+void TunerPlaybackAidlTest::playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf) {
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    int64_t filterId;
+
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    mFilterTests.setDemux(demux);
+    mDvrTests.setDemux(demux);
+    ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
+    ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrConf.settings));
+    ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
+    mDvrTests.startPlaybackInputThread(dvrConf.playbackInputFile,
+                                       dvrConf.settings.get<DvrSettings::Tag::playback>());
+    ASSERT_TRUE(mDvrTests.startDvrPlayback());
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    ASSERT_TRUE(filterDataOutputTest());
+    mDvrTests.stopPlaybackThread();
+    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    ASSERT_TRUE(mDvrTests.stopDvrPlayback());
+    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+    mDvrTests.closeDvrPlayback();
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
+void TunerRecordAidlTest::recordSingleFilterTestWithLnb(FilterConfig filterConf,
+                                                        FrontendConfig frontendConf,
+                                                        DvrConfig dvrConf, LnbConfig lnbConf) {
+    if (lnbConf.name.compare(emptyHardwareId) == 0) {
+        vector<int32_t> ids;
+        ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+        ASSERT_TRUE(ids.size() > 0);
+        ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+        mLnbId = &ids[0];
+    } else {
+        mLnbId = (int32_t*)malloc(sizeof(int32_t));
+        ASSERT_TRUE(mLnbTests.openLnbByName(lnbConf.name, *mLnbId));
+    }
+    ASSERT_TRUE(mLnbTests.setLnbCallback());
+    ASSERT_TRUE(mLnbTests.setVoltage(lnbConf.voltage));
+    ASSERT_TRUE(mLnbTests.setTone(lnbConf.tone));
+    ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbConf.position));
+    for (auto msgName : lnbRecord.diseqcMsgs) {
+        ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgMap[msgName]));
+    }
+    recordSingleFilterTest(filterConf, frontendConf, dvrConf);
+    ASSERT_TRUE(mLnbTests.closeLnb());
+    mLnbId = nullptr;
+}
+
+void TunerRecordAidlTest::attachSingleFilterToRecordDvrTest(FilterConfig filterConf,
+                                                            FrontendConfig frontendConf,
+                                                            DvrConfig dvrConf) {
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    mDvrTests.setDemux(demux);
+
+    DvrConfig dvrSourceConfig;
+    if (record.hasFrontendConnection) {
+        int32_t feId;
+        mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+        ASSERT_TRUE(feId != INVALID_ID);
+        ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+        ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+        ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    } else {
+        dvrSourceConfig = dvrMap[record.dvrSourceId];
+        ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrSourceConfig.type, dvrSourceConfig.bufferSize));
+        ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrSourceConfig.settings));
+        ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
+    }
+
+    int64_t filterId;
+    std::shared_ptr<IFilter> filter;
+    mFilterTests.setDemux(demux);
+
+    ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
+    ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
+    ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
+
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
+    filter = mFilterTests.getFilterById(filterId);
+    ASSERT_TRUE(filter != nullptr);
+    ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
+    ASSERT_TRUE(mDvrTests.startDvrRecord());
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    ASSERT_TRUE(mDvrTests.stopDvrRecord());
+    ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
+    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+    mDvrTests.closeDvrRecord();
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+
+    if (record.hasFrontendConnection) {
+        ASSERT_TRUE(mFrontendTests.closeFrontend());
+    }
+}
+
+void TunerRecordAidlTest::recordSingleFilterTest(FilterConfig filterConf,
+                                                 FrontendConfig frontendConf, DvrConfig dvrConf) {
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    mDvrTests.setDemux(demux);
+
+    DvrConfig dvrSourceConfig;
+    if (record.hasFrontendConnection) {
+        int32_t feId;
+        mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+        ASSERT_TRUE(feId != INVALID_ID);
+        ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+        ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+        if (frontendConf.isSoftwareFe) {
+            mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[record.dvrSoftwareFeId]);
+        }
+        ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+        mFrontendTests.setDvrTests(&mDvrTests);
+    } else {
+        dvrSourceConfig = dvrMap[record.dvrSourceId];
+        ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrSourceConfig.type, dvrSourceConfig.bufferSize));
+        ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrSourceConfig.settings));
+        ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
+    }
+
+    int64_t filterId;
+    std::shared_ptr<IFilter> filter;
+    mFilterTests.setDemux(demux);
+    ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
+    ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
+    ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
+    filter = mFilterTests.getFilterById(filterId);
+    ASSERT_TRUE(filter != nullptr);
+    mDvrTests.startRecordOutputThread(dvrConf.settings.get<DvrSettings::Tag::record>());
+    ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
+    ASSERT_TRUE(mDvrTests.startDvrRecord());
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+
+    if (record.hasFrontendConnection) {
+        ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+    } else {
+        // Start DVR Source
+        mDvrTests.startPlaybackInputThread(
+                dvrSourceConfig.playbackInputFile,
+                dvrSourceConfig.settings.get<DvrSettings::Tag::playback>());
+        ASSERT_TRUE(mDvrTests.startDvrPlayback());
+    }
+
+    mDvrTests.testRecordOutput();
+    mDvrTests.stopRecordThread();
+
+    if (record.hasFrontendConnection) {
+        ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
+    } else {
+        mDvrTests.stopPlaybackThread();
+        ASSERT_TRUE(mDvrTests.stopDvrPlayback());
+    }
+
+    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    ASSERT_TRUE(mDvrTests.stopDvrRecord());
+    ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
+    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+    mDvrTests.closeDvrRecord();
+
+    if (record.hasFrontendConnection) {
+        ASSERT_TRUE(mFrontendTests.closeFrontend());
+    } else {
+        mDvrTests.closeDvrPlayback();
+    }
+
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
+void TunerDescramblerAidlTest::scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
+                                                      FrontendConfig frontendConf,
+                                                      DescramblerConfig descConfig) {
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+
+    DvrConfig dvrSourceConfig;
+    if (descrambling.hasFrontendConnection) {
+        int32_t feId;
+        mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+        ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+        ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+        if (frontendConf.isSoftwareFe) {
+            mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[descrambling.dvrSoftwareFeId]);
+        }
+        ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+        mFrontendTests.setDemux(demux);
+    } else {
+        dvrSourceConfig = dvrMap[descrambling.dvrSourceId];
+        mDvrTests.setDemux(demux);
+        ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrSourceConfig.type, dvrSourceConfig.bufferSize));
+        ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrSourceConfig.settings));
+        ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
+    }
+
+    set<int64_t> filterIds;
+    int64_t filterId;
+    set<struct FilterConfig>::iterator config;
+    set<int64_t>::iterator id;
+    mFilterTests.setDemux(demux);
+    for (config = mediaFilterConfs.begin(); config != mediaFilterConfs.end(); config++) {
+        ASSERT_TRUE(mFilterTests.openFilterInDemux((*config).type, (*config).bufferSize));
+        ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
+        ASSERT_TRUE(mFilterTests.configFilter((*config).settings, filterId));
+        filterIds.insert(filterId);
+    }
+    ASSERT_TRUE(mDescramblerTests.openDescrambler(demuxId));
+    vector<uint8_t> token;
+    ASSERT_TRUE(mDescramblerTests.getKeyToken(descConfig.casSystemId, descConfig.provisionStr,
+                                              descConfig.hidlPvtData, token));
+    mDescramblerTests.setKeyToken(token);
+    vector<DemuxPid> pids;
+    DemuxPid pid;
+    for (config = mediaFilterConfs.begin(); config != mediaFilterConfs.end(); config++) {
+        ASSERT_TRUE(mDescramblerTests.getDemuxPidFromFilterSettings((*config).type,
+                                                                    (*config).settings, pid));
+        pids.push_back(pid);
+        ASSERT_TRUE(mDescramblerTests.addPid(pid, nullptr));
+    }
+    for (id = filterIds.begin(); id != filterIds.end(); id++) {
+        ASSERT_TRUE(mFilterTests.startFilter(*id));
+    }
+
+    if (descrambling.hasFrontendConnection) {
+        // tune test
+        ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+    } else {
+        // Start DVR Source
+        mDvrTests.startPlaybackInputThread(
+                dvrSourceConfig.playbackInputFile,
+                dvrSourceConfig.settings.get<DvrSettings::Tag::playback>());
+        ASSERT_TRUE(mDvrTests.startDvrPlayback());
+    }
+
+    ASSERT_TRUE(filterDataOutputTest());
+
+    if (descrambling.hasFrontendConnection) {
+        ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
+    } else {
+        mDvrTests.stopPlaybackThread();
+        ASSERT_TRUE(mDvrTests.stopDvrPlayback());
+    }
+
+    for (id = filterIds.begin(); id != filterIds.end(); id++) {
+        ASSERT_TRUE(mFilterTests.stopFilter(*id));
+    }
+    for (auto pid : pids) {
+        ASSERT_TRUE(mDescramblerTests.removePid(pid, nullptr));
+    }
+    ASSERT_TRUE(mDescramblerTests.closeDescrambler());
+    for (id = filterIds.begin(); id != filterIds.end(); id++) {
+        ASSERT_TRUE(mFilterTests.closeFilter(*id));
+    }
+
+    if (descrambling.hasFrontendConnection) {
+        ASSERT_TRUE(mFrontendTests.closeFrontend());
+    } else {
+        mDvrTests.closeDvrPlayback();
+    }
+
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
+TEST_P(TunerLnbAidlTest, SendDiseqcMessageToLnb) {
+    description("Open and configure an Lnb with specific settings then send a diseqc msg to it.");
+    if (!lnbLive.support) {
+        return;
+    }
+    if (lnbMap[lnbLive.lnbId].name.compare(emptyHardwareId) == 0) {
+        vector<int32_t> ids;
+        ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+        ASSERT_TRUE(ids.size() > 0);
+        ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+    } else {
+        int32_t id;
+        ASSERT_TRUE(mLnbTests.openLnbByName(lnbMap[lnbLive.lnbId].name, id));
+    }
+    ASSERT_TRUE(mLnbTests.setLnbCallback());
+    ASSERT_TRUE(mLnbTests.setVoltage(lnbMap[lnbLive.lnbId].voltage));
+    ASSERT_TRUE(mLnbTests.setTone(lnbMap[lnbLive.lnbId].tone));
+    ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbMap[lnbLive.lnbId].position));
+    for (auto msgName : lnbLive.diseqcMsgs) {
+        ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgMap[msgName]));
+    }
+    ASSERT_TRUE(mLnbTests.closeLnb());
+}
+
+TEST_P(TunerDemuxAidlTest, openDemux) {
+    description("Open and close a Demux.");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    int32_t feId;
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    mFrontendTests.getFrontendIdByType(frontendMap[live.frontendId].type, feId);
+    ASSERT_TRUE(feId != INVALID_ID);
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+TEST_P(TunerDemuxAidlTest, getAvSyncTime) {
+    description("Get the A/V sync time from a PCR filter.");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    if (live.pcrFilterId.compare(emptyHardwareId) == 0) {
+        return;
+    }
+    int32_t feId;
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    int64_t mediaFilterId;
+    int64_t pcrFilterId;
+    int32_t avSyncHwId;
+    std::shared_ptr<IFilter> mediaFilter;
+
+    mFrontendTests.getFrontendIdByType(frontendMap[live.frontendId].type, feId);
+    ASSERT_TRUE(feId != INVALID_ID);
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    mFilterTests.setDemux(demux);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterMap[live.videoFilterId].type,
+                                               filterMap[live.videoFilterId].bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(mediaFilterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterMap[live.videoFilterId].settings, mediaFilterId));
+    mediaFilter = mFilterTests.getFilterById(mediaFilterId);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterMap[live.pcrFilterId].type,
+                                               filterMap[live.pcrFilterId].bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(pcrFilterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterMap[live.pcrFilterId].settings, pcrFilterId));
+    ASSERT_TRUE(mDemuxTests.getAvSyncId(mediaFilter, avSyncHwId));
+    ASSERT_TRUE(pcrFilterId == avSyncHwId);
+    ASSERT_TRUE(mDemuxTests.getAvSyncTime(pcrFilterId));
+    ASSERT_TRUE(mFilterTests.closeFilter(pcrFilterId));
+    ASSERT_TRUE(mFilterTests.closeFilter(mediaFilterId));
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+TEST_P(TunerFilterAidlTest, StartFilterInDemux) {
+    description("Open and start a filter in Demux.");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    // TODO use parameterized tests
+    configSingleFilterInDemuxTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerFilterAidlTest, ConfigIpFilterInDemuxWithCid) {
+    description("Open and configure an ip filter in Demux.");
+    // TODO use parameterized tests
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    if (live.ipFilterId.compare(emptyHardwareId) == 0) {
+        return;
+    }
+    configSingleFilterInDemuxTest(filterMap[live.ipFilterId], frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerFilterAidlTest, ReconfigFilterToReceiveStartId) {
+    description("Recofigure and restart a filter to test start id.");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    // TODO use parameterized tests
+    reconfigSingleFilterInDemuxTest(filterMap[live.videoFilterId], filterMap[live.videoFilterId],
+                                    frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerFilterAidlTest, SetFilterLinkage) {
+    description("Pick up all the possible linkages from the demux caps and set them up.");
+    DemuxCapabilities caps;
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.getDemuxCaps(caps));
+    mFilterTests.setDemux(demux);
+    for (int i = 0; i < caps.linkCaps.size(); i++) {
+        uint32_t bitMask = 1;
+        for (int j = 0; j < FILTER_MAIN_TYPE_BIT_COUNT; j++) {
+            if (caps.linkCaps[i] & (bitMask << j)) {
+                int64_t sourceFilterId;
+                int64_t sinkFilterId;
+                ASSERT_TRUE(mFilterTests.openFilterInDemux(getLinkageFilterType(i), FMQ_SIZE_16M));
+                ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(sourceFilterId));
+                ASSERT_TRUE(mFilterTests.openFilterInDemux(getLinkageFilterType(j), FMQ_SIZE_16M));
+                ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(sinkFilterId));
+                ASSERT_TRUE(mFilterTests.setFilterDataSource(sourceFilterId, sinkFilterId));
+                ASSERT_TRUE(mFilterTests.setFilterDataSourceToDemux(sinkFilterId));
+                ASSERT_TRUE(mFilterTests.closeFilter(sinkFilterId));
+                ASSERT_TRUE(mFilterTests.closeFilter(sourceFilterId));
+            }
+        }
+    }
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
+TEST_P(TunerFilterAidlTest, testTimeFilter) {
+    description("Open a timer filter in Demux and set time stamp.");
+    if (!timeFilter.support) {
+        return;
+    }
+    // TODO use parameterized tests
+    testTimeFilter(timeFilterMap[timeFilter.timeFilterId]);
+}
+
+static bool isMediaFilter(const FilterConfig& filterConfig) {
+    switch (filterConfig.type.mainType) {
+        case DemuxFilterMainType::TS: {
+            // TS Audio and Video filters are media filters
+            auto tsFilterType =
+                    filterConfig.type.subType.get<DemuxFilterSubType::Tag::tsFilterType>();
+            return (tsFilterType == DemuxTsFilterType::AUDIO ||
+                    tsFilterType == DemuxTsFilterType::VIDEO);
+        }
+        case DemuxFilterMainType::MMTP: {
+            // MMTP Audio and Video filters are media filters
+            auto mmtpFilterType =
+                    filterConfig.type.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>();
+            return (mmtpFilterType == DemuxMmtpFilterType::AUDIO ||
+                    mmtpFilterType == DemuxMmtpFilterType::VIDEO);
+        }
+        default:
+            return false;
+    }
+}
+
+static int getDemuxFilterEventDataLength(const DemuxFilterEvent& event) {
+    switch (event.getTag()) {
+        case DemuxFilterEvent::Tag::section:
+            return event.get<DemuxFilterEvent::Tag::section>().dataLength;
+        case DemuxFilterEvent::Tag::media:
+            return event.get<DemuxFilterEvent::Tag::media>().dataLength;
+        case DemuxFilterEvent::Tag::pes:
+            return event.get<DemuxFilterEvent::Tag::pes>().dataLength;
+        case DemuxFilterEvent::Tag::download:
+            return event.get<DemuxFilterEvent::Tag::download>().dataLength;
+        case DemuxFilterEvent::Tag::ipPayload:
+            return event.get<DemuxFilterEvent::Tag::ipPayload>().dataLength;
+
+        case DemuxFilterEvent::Tag::tsRecord:
+        case DemuxFilterEvent::Tag::mmtpRecord:
+        case DemuxFilterEvent::Tag::temi:
+        case DemuxFilterEvent::Tag::monitorEvent:
+        case DemuxFilterEvent::Tag::startId:
+            return 0;
+    }
+}
+
+// TODO: move boilerplate into text fixture
+void TunerFilterAidlTest::testDelayHint(const FilterConfig& filterConf) {
+    int32_t feId;
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    int64_t filterId;
+
+    mFrontendTests.getFrontendIdByType(frontendMap[live.frontendId].type, feId);
+    ASSERT_TRUE(feId != INVALID_ID);
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    mFilterTests.setDemux(demux);
+
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
+
+    bool mediaFilter = isMediaFilter(filterConf);
+    auto filter = mFilterTests.getFilterById(filterId);
+
+    // startTime needs to be set before calling setDelayHint.
+    auto startTime = std::chrono::steady_clock::now();
+
+    auto timeDelayInMs = std::chrono::milliseconds(filterConf.timeDelayInMs);
+    if (timeDelayInMs.count() > 0) {
+        FilterDelayHint delayHint;
+        delayHint.hintType = FilterDelayHintType::TIME_DELAY_IN_MS;
+        delayHint.hintValue = timeDelayInMs.count();
+
+        // setDelayHint should fail for media filters.
+        ASSERT_EQ(filter->setDelayHint(delayHint).isOk(), !mediaFilter);
+    }
+
+    int dataDelayInBytes = filterConf.dataDelayInBytes;
+    if (dataDelayInBytes > 0) {
+        FilterDelayHint delayHint;
+        delayHint.hintType = FilterDelayHintType::DATA_SIZE_DELAY_IN_BYTES;
+        delayHint.hintValue = dataDelayInBytes;
+
+        // setDelayHint should fail for media filters.
+        ASSERT_EQ(filter->setDelayHint(delayHint).isOk(), !mediaFilter);
+    }
+
+    // start and stop filter (and wait for first callback) in order to
+    // circumvent callback scheduler race conditions after adjusting filter
+    // delays.
+    auto cb = mFilterTests.getFilterCallbacks().at(filterId);
+    auto future =
+            cb->verifyFilterCallback([](const std::vector<DemuxFilterEvent>&) { return true; });
+    mFilterTests.startFilter(filterId);
+
+    auto timeout = std::chrono::seconds(30);
+    ASSERT_EQ(future.wait_for(timeout), std::future_status::ready);
+
+    mFilterTests.stopFilter(filterId);
+
+    if (!mediaFilter) {
+        int callbackSize = 0;
+        future = cb->verifyFilterCallback(
+                [&callbackSize](const std::vector<DemuxFilterEvent>& events) {
+                    for (const auto& event : events) {
+                        callbackSize += getDemuxFilterEventDataLength(event);
+                    }
+                    return true;
+                });
+
+        // The configure stage can also produce events, so we should set the delay
+        // hint beforehand.
+        ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+
+        ASSERT_TRUE(mFilterTests.startFilter(filterId));
+
+        // block and wait for callback to be received.
+        ASSERT_EQ(future.wait_for(timeout), std::future_status::ready);
+        auto duration = std::chrono::steady_clock::now() - startTime;
+
+        bool delayHintTest = duration >= timeDelayInMs;
+        bool dataSizeTest = callbackSize >= dataDelayInBytes;
+
+        if (timeDelayInMs.count() > 0 && dataDelayInBytes > 0) {
+            ASSERT_TRUE(delayHintTest || dataSizeTest);
+        } else {
+            // if only one of time delay / data delay is configured, one of them
+            // holds true by default, so we want both assertions to be true.
+            ASSERT_TRUE(delayHintTest && dataSizeTest);
+        }
+
+        ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    }
+
+    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+TEST_P(TunerFilterAidlTest, FilterDelayHintTest) {
+    description("Test filter time delay hint.");
+
+    for (const auto& obj : filterMap) {
+        testDelayHint(obj.second);
+    }
+}
+
+TEST_P(TunerPlaybackAidlTest, PlaybackDataFlowWithTsSectionFilterTest) {
+    description("Feed ts data from playback and configure Ts section filter to get output");
+    if (!playback.support || playback.sectionFilterId.compare(emptyHardwareId) == 0) {
+        return;
+    }
+    playbackSingleFilterTest(filterMap[playback.sectionFilterId], dvrMap[playback.dvrId]);
+}
+
+TEST_P(TunerPlaybackAidlTest, PlaybackDataFlowWithTsAudioFilterTest) {
+    description("Feed ts data from playback and configure Ts audio filter to get output");
+    if (!playback.support) {
+        return;
+    }
+    playbackSingleFilterTest(filterMap[playback.audioFilterId], dvrMap[playback.dvrId]);
+}
+
+TEST_P(TunerPlaybackAidlTest, PlaybackDataFlowWithTsVideoFilterTest) {
+    description("Feed ts data from playback and configure Ts video filter to get output");
+    if (!playback.support) {
+        return;
+    }
+    playbackSingleFilterTest(filterMap[playback.videoFilterId], dvrMap[playback.dvrId]);
+}
+
+TEST_P(TunerRecordAidlTest, RecordDataFlowWithTsRecordFilterTest) {
+    description("Feed ts data from frontend to recording and test with ts record filter");
+    if (!record.support) {
+        return;
+    }
+    recordSingleFilterTest(filterMap[record.recordFilterId], frontendMap[record.frontendId],
+                           dvrMap[record.dvrRecordId]);
+}
+
+TEST_P(TunerRecordAidlTest, AttachFiltersToRecordTest) {
+    description("Attach a single filter to the record dvr test.");
+    // TODO use parameterized tests
+    if (!record.support) {
+        return;
+    }
+    attachSingleFilterToRecordDvrTest(filterMap[record.recordFilterId],
+                                      frontendMap[record.frontendId], dvrMap[record.dvrRecordId]);
+}
+
+TEST_P(TunerRecordAidlTest, LnbRecordDataFlowWithTsRecordFilterTest) {
+    description("Feed ts data from Fe with Lnb to recording and test with ts record filter");
+    if (!lnbRecord.support) {
+        return;
+    }
+    recordSingleFilterTestWithLnb(filterMap[lnbRecord.recordFilterId],
+                                  frontendMap[lnbRecord.frontendId], dvrMap[lnbRecord.dvrRecordId],
+                                  lnbMap[lnbRecord.lnbId]);
+}
+
+TEST_P(TunerFrontendAidlTest, TuneFrontend) {
+    description("Tune one Frontend with specific setting and check Lock event");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    mFrontendTests.tuneTest(frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerFrontendAidlTest, AutoScanFrontend) {
+    description("Run an auto frontend scan with specific setting and check lock scanMessage");
+    if (!scan.hasFrontendConnection) {
+        return;
+    }
+    mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_AUTO);
+}
+
+TEST_P(TunerFrontendAidlTest, BlindScanFrontend) {
+    description("Run an blind frontend scan with specific setting and check lock scanMessage");
+    if (!scan.hasFrontendConnection) {
+        return;
+    }
+    mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND);
+}
+
+TEST_P(TunerFrontendAidlTest, TuneFrontendWithFrontendSettings) {
+    description("Tune one Frontend with setting and check Lock event");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    mFrontendTests.tuneTest(frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerFrontendAidlTest, BlindScanFrontendWithEndFrequency) {
+    description("Run an blind frontend scan with setting and check lock scanMessage");
+    if (!scan.hasFrontendConnection) {
+        return;
+    }
+    mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND);
+}
+
+TEST_P(TunerFrontendAidlTest, LinkToCiCam) {
+    description("Test Frontend link to CiCam");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    if (!frontendMap[live.frontendId].canConnectToCiCam) {
+        return;
+    }
+    mFrontendTests.tuneTest(frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerFrontendAidlTest, getHardwareInfo) {
+    description("Test Frontend get hardware info");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    mFrontendTests.debugInfoTest(frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerBroadcastAidlTest, BroadcastDataFlowVideoFilterTest) {
+    description("Test Video Filter functionality in Broadcast use case.");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    broadcastSingleFilterTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerBroadcastAidlTest, BroadcastDataFlowAudioFilterTest) {
+    description("Test Audio Filter functionality in Broadcast use case.");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    broadcastSingleFilterTest(filterMap[live.audioFilterId], frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerBroadcastAidlTest, BroadcastDataFlowSectionFilterTest) {
+    description("Test Section Filter functionality in Broadcast use case.");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    if (live.sectionFilterId.compare(emptyHardwareId) == 0) {
+        return;
+    }
+    broadcastSingleFilterTest(filterMap[live.sectionFilterId], frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerBroadcastAidlTest, IonBufferTest) {
+    description("Test the av filter data bufferring.");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    broadcastSingleFilterTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerBroadcastAidlTest, LnbBroadcastDataFlowVideoFilterTest) {
+    description("Test Video Filter functionality in Broadcast with Lnb use case.");
+    if (!lnbLive.support) {
+        return;
+    }
+    broadcastSingleFilterTestWithLnb(filterMap[lnbLive.videoFilterId],
+                                     frontendMap[lnbLive.frontendId], lnbMap[lnbLive.lnbId]);
+}
+
+TEST_P(TunerBroadcastAidlTest, MediaFilterWithSharedMemoryHandle) {
+    description("Test the Media Filter with shared memory handle");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
+    mediaFilterUsingSharedMemoryTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]);
+}
+
+TEST_P(TunerDescramblerAidlTest, CreateDescrambler) {
+    description("Create Descrambler");
+    if (!descrambling.support) {
+        return;
+    }
+    int32_t demuxId;
+    std::shared_ptr<IDemux> demux;
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+
+    if (descrambling.hasFrontendConnection) {
+        int32_t feId;
+        mFrontendTests.getFrontendIdByType(frontendMap[descrambling.frontendId].type, feId);
+        ASSERT_TRUE(feId != INVALID_ID);
+        ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+        ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+        ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    }
+
+    ASSERT_TRUE(mDescramblerTests.openDescrambler(demuxId));
+    ASSERT_TRUE(mDescramblerTests.closeDescrambler());
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+
+    if (descrambling.hasFrontendConnection) {
+        ASSERT_TRUE(mFrontendTests.closeFrontend());
+    }
+}
+
+TEST_P(TunerDescramblerAidlTest, ScrambledBroadcastDataFlowMediaFiltersTest) {
+    description("Test ts audio filter in scrambled broadcast use case");
+    if (!descrambling.support) {
+        return;
+    }
+    set<FilterConfig> filterConfs;
+    filterConfs.insert(static_cast<FilterConfig>(filterMap[descrambling.audioFilterId]));
+    filterConfs.insert(static_cast<FilterConfig>(filterMap[descrambling.videoFilterId]));
+    scrambledBroadcastTest(filterConfs, frontendMap[descrambling.frontendId],
+                           descramblerMap[descrambling.descramblerId]);
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, TunerBroadcastAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(ITuner::descriptor)),
+                         android::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, TunerFrontendAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(ITuner::descriptor)),
+                         android::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, TunerFilterAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(ITuner::descriptor)),
+                         android::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, TunerRecordAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(ITuner::descriptor)),
+                         android::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, TunerLnbAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(ITuner::descriptor)),
+                         android::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, TunerDemuxAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(ITuner::descriptor)),
+                         android::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, TunerPlaybackAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(ITuner::descriptor)),
+                         android::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, TunerDescramblerAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(ITuner::descriptor)),
+                         android::PrintInstanceNameToString);
+
+}  // namespace
+
+// Start thread pool to receive callbacks from AIDL service.
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
new file mode 100644
index 0000000..7f80d90
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
@@ -0,0 +1,373 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_manager.h>
+
+#include "DemuxTests.h"
+#include "DescramblerTests.h"
+#include "DvrTests.h"
+#include "FrontendTests.h"
+#include "LnbTests.h"
+
+using android::sp;
+
+namespace {
+
+bool initConfiguration() {
+    TunerTestingConfigAidlReader1_0::setConfigFilePath(configFilePath);
+    if (!TunerTestingConfigAidlReader1_0::checkConfigFileExists()) {
+        return false;
+    }
+    initFrontendConfig();
+    initFilterConfig();
+    initDvrConfig();
+    connectHardwaresToTestCases();
+    if (!validateConnections()) {
+        ALOGW("[vts] failed to validate connections.");
+        return false;
+    }
+    return true;
+}
+
+static AssertionResult success() {
+    return ::testing::AssertionSuccess();
+}
+
+AssertionResult filterDataOutputTestBase(FilterTests& tests) {
+    // Data Verify Module
+    std::map<int64_t, std::shared_ptr<FilterCallback>>::iterator it;
+    std::map<int64_t, std::shared_ptr<FilterCallback>> filterCallbacks = tests.getFilterCallbacks();
+    for (it = filterCallbacks.begin(); it != filterCallbacks.end(); it++) {
+        it->second->testFilterDataOutput();
+    }
+    return success();
+}
+
+class TunerLnbAidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        if (AServiceManager_isDeclared(GetParam().c_str())) {
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+            mService = ITuner::fromBinder(binder);
+        } else {
+            mService = nullptr;
+        }
+        ASSERT_NE(mService, nullptr);
+        ASSERT_TRUE(initConfiguration());
+
+        mLnbTests.setService(mService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    std::shared_ptr<ITuner> mService;
+    LnbTests mLnbTests;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerLnbAidlTest);
+
+class TunerDemuxAidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        if (AServiceManager_isDeclared(GetParam().c_str())) {
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+            mService = ITuner::fromBinder(binder);
+        } else {
+            mService = nullptr;
+        }
+        ASSERT_NE(mService, nullptr);
+        ASSERT_TRUE(initConfiguration());
+
+        mFrontendTests.setService(mService);
+        mDemuxTests.setService(mService);
+        mFilterTests.setService(mService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    std::shared_ptr<ITuner> mService;
+    FrontendTests mFrontendTests;
+    DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerDemuxAidlTest);
+
+class TunerFilterAidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        if (AServiceManager_isDeclared(GetParam().c_str())) {
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+            mService = ITuner::fromBinder(binder);
+        } else {
+            mService = nullptr;
+        }
+        ASSERT_NE(mService, nullptr);
+        initConfiguration();
+
+        mFrontendTests.setService(mService);
+        mDemuxTests.setService(mService);
+        mFilterTests.setService(mService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    void configSingleFilterInDemuxTest(FilterConfig filterConf, FrontendConfig frontendConf);
+    void reconfigSingleFilterInDemuxTest(FilterConfig filterConf, FilterConfig filterReconf,
+                                         FrontendConfig frontendConf);
+    void testTimeFilter(TimeFilterConfig filterConf);
+    void testDelayHint(const FilterConfig& filterConf);
+
+    DemuxFilterType getLinkageFilterType(int bit) {
+        DemuxFilterType type;
+        type.mainType = static_cast<DemuxFilterMainType>(1 << bit);
+        switch (type.mainType) {
+            case DemuxFilterMainType::TS:
+                type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+                        DemuxTsFilterType::UNDEFINED);
+                break;
+            case DemuxFilterMainType::MMTP:
+                type.subType.set<DemuxFilterSubType::Tag::mmtpFilterType>(
+                        DemuxMmtpFilterType::UNDEFINED);
+                break;
+            case DemuxFilterMainType::IP:
+                type.subType.set<DemuxFilterSubType::Tag::ipFilterType>(
+                        DemuxIpFilterType::UNDEFINED);
+                break;
+            case DemuxFilterMainType::TLV:
+                type.subType.set<DemuxFilterSubType::Tag::tlvFilterType>(
+                        DemuxTlvFilterType::UNDEFINED);
+                break;
+            case DemuxFilterMainType::ALP:
+                type.subType.set<DemuxFilterSubType::Tag::alpFilterType>(
+                        DemuxAlpFilterType::UNDEFINED);
+                break;
+            default:
+                break;
+        }
+        return type;
+    }
+    std::shared_ptr<ITuner> mService;
+    FrontendTests mFrontendTests;
+    DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFilterAidlTest);
+
+class TunerPlaybackAidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        if (AServiceManager_isDeclared(GetParam().c_str())) {
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+            mService = ITuner::fromBinder(binder);
+        } else {
+            mService = nullptr;
+        }
+        ASSERT_NE(mService, nullptr);
+        ASSERT_TRUE(initConfiguration());
+
+        mFrontendTests.setService(mService);
+        mDemuxTests.setService(mService);
+        mFilterTests.setService(mService);
+        mDvrTests.setService(mService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    std::shared_ptr<ITuner> mService;
+    FrontendTests mFrontendTests;
+    DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
+    DvrTests mDvrTests;
+
+    AssertionResult filterDataOutputTest();
+
+    void playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf);
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerPlaybackAidlTest);
+
+class TunerRecordAidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        if (AServiceManager_isDeclared(GetParam().c_str())) {
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+            mService = ITuner::fromBinder(binder);
+        } else {
+            mService = nullptr;
+        }
+        ASSERT_NE(mService, nullptr);
+        initConfiguration();
+
+        mFrontendTests.setService(mService);
+        mDemuxTests.setService(mService);
+        mFilterTests.setService(mService);
+        mDvrTests.setService(mService);
+        mLnbTests.setService(mService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    void attachSingleFilterToRecordDvrTest(FilterConfig filterConf, FrontendConfig frontendConf,
+                                           DvrConfig dvrConf);
+    void recordSingleFilterTestWithLnb(FilterConfig filterConf, FrontendConfig frontendConf,
+                                       DvrConfig dvrConf, LnbConfig lnbConf);
+    void recordSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf,
+                                DvrConfig dvrConf);
+
+    std::shared_ptr<ITuner> mService;
+    FrontendTests mFrontendTests;
+    DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
+    DvrTests mDvrTests;
+    LnbTests mLnbTests;
+
+  private:
+    int32_t* mLnbId = nullptr;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerRecordAidlTest);
+
+class TunerFrontendAidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        if (AServiceManager_isDeclared(GetParam().c_str())) {
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+            mService = ITuner::fromBinder(binder);
+        } else {
+            mService = nullptr;
+        }
+        ASSERT_NE(mService, nullptr);
+        initConfiguration();
+
+        mFrontendTests.setService(mService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    std::shared_ptr<ITuner> mService;
+    FrontendTests mFrontendTests;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFrontendAidlTest);
+
+class TunerBroadcastAidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        if (AServiceManager_isDeclared(GetParam().c_str())) {
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+            mService = ITuner::fromBinder(binder);
+        } else {
+            mService = nullptr;
+        }
+        ASSERT_NE(mService, nullptr);
+        initConfiguration();
+
+        mFrontendTests.setService(mService);
+        mDemuxTests.setService(mService);
+        mFilterTests.setService(mService);
+        mLnbTests.setService(mService);
+        mDvrTests.setService(mService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    std::shared_ptr<ITuner> mService;
+    FrontendTests mFrontendTests;
+    DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
+    LnbTests mLnbTests;
+    DvrTests mDvrTests;
+
+    AssertionResult filterDataOutputTest();
+
+    void broadcastSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf);
+    void broadcastSingleFilterTestWithLnb(FilterConfig filterConf, FrontendConfig frontendConf,
+                                          LnbConfig lnbConf);
+    void mediaFilterUsingSharedMemoryTest(FilterConfig filterConf, FrontendConfig frontendConf);
+
+  private:
+    int32_t* mLnbId = nullptr;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerBroadcastAidlTest);
+
+class TunerDescramblerAidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        if (AServiceManager_isDeclared(GetParam().c_str())) {
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+            mService = ITuner::fromBinder(binder);
+        } else {
+            mService = nullptr;
+        }
+        mCasService = IMediaCasService::getService();
+        ASSERT_NE(mService, nullptr);
+        ASSERT_NE(mCasService, nullptr);
+        ASSERT_TRUE(initConfiguration());
+
+        mFrontendTests.setService(mService);
+        mDemuxTests.setService(mService);
+        mDvrTests.setService(mService);
+        mDescramblerTests.setService(mService);
+        mDescramblerTests.setCasService(mCasService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    void scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
+                                FrontendConfig frontendConf, DescramblerConfig descConfig);
+    AssertionResult filterDataOutputTest();
+
+    std::shared_ptr<ITuner> mService;
+    android::sp<IMediaCasService> mCasService;
+    FrontendTests mFrontendTests;
+    DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
+    DescramblerTests mDescramblerTests;
+    DvrTests mDvrTests;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerDescramblerAidlTest);
+
+}  // namespace
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
new file mode 100644
index 0000000..5a72ba4
--- /dev/null
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
@@ -0,0 +1,218 @@
+/*
+ * 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.
+ */
+
+#include <binder/MemoryDealer.h>
+
+#include "../../../config/TunerTestingConfigAidlReaderV1_0.h"
+
+#include <aidl/android/hardware/tv/tuner/DataFormat.h>
+#include <aidl/android/hardware/tv/tuner/DemuxAlpFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterMainType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterMonitorEventType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxIpAddress.h>
+#include <aidl/android/hardware/tv/tuner/DemuxIpFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxIpFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxMmtpFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxRecordScIndexType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxTsFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DvrSettings.h>
+#include <aidl/android/hardware/tv/tuner/DvrType.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtBandwidth.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtCoderate.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtConstellation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtGuardInterval.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtHierarchy.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtStandard.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendType.h>
+#include <aidl/android/hardware/tv/tuner/PlaybackSettings.h>
+#include <aidl/android/hardware/tv/tuner/RecordSettings.h>
+
+using namespace std;
+using namespace aidl::android::hardware::tv::tuner;
+using namespace android::media::tuner::testing::configuration::V1_0;
+
+const int32_t FMQ_SIZE_4M = 0x400000;
+const int32_t FMQ_SIZE_16M = 0x1000000;
+
+const string configFilePath = "/vendor/etc/tuner_vts_config_aidl_V1.xml";
+
+#define FILTER_MAIN_TYPE_BIT_COUNT 5
+
+// Hardware configs
+static map<string, FrontendConfig> frontendMap;
+static map<string, FilterConfig> filterMap;
+static map<string, DvrConfig> dvrMap;
+static map<string, LnbConfig> lnbMap;
+static map<string, TimeFilterConfig> timeFilterMap;
+static map<string, vector<uint8_t>> diseqcMsgMap;
+static map<string, DescramblerConfig> descramblerMap;
+
+// Hardware and test cases connections
+static LiveBroadcastHardwareConnections live;
+static ScanHardwareConnections scan;
+static DvrPlaybackHardwareConnections playback;
+static DvrRecordHardwareConnections record;
+static DescramblingHardwareConnections descrambling;
+static LnbLiveHardwareConnections lnbLive;
+static LnbRecordHardwareConnections lnbRecord;
+static TimeFilterHardwareConnections timeFilter;
+
+/** Config all the frontends that would be used in the tests */
+inline void initFrontendConfig() {
+    // The test will use the internal default fe when default fe is connected to any data flow
+    // without overriding in the xml config.
+    string defaultFeId = "FE_DEFAULT";
+    FrontendDvbtSettings dvbtSettings{
+            .frequency = 578000000,
+            .transmissionMode = FrontendDvbtTransmissionMode::AUTO,
+            .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
+            .isHighPriority = true,
+    };
+    frontendMap[defaultFeId].type = FrontendType::DVBT;
+    frontendMap[defaultFeId].settings.set<FrontendSettings::Tag::dvbt>(dvbtSettings);
+
+    vector<FrontendStatusType> types;
+    types.push_back(FrontendStatusType::UEC);
+    types.push_back(FrontendStatusType::IS_MISO);
+
+    vector<FrontendStatus> statuses;
+    FrontendStatus status;
+    status.set<FrontendStatus::Tag::uec>(4);
+    statuses.push_back(status);
+    status.set<FrontendStatus::Tag::isMiso>(true);
+    statuses.push_back(status);
+
+    frontendMap[defaultFeId].tuneStatusTypes = types;
+    frontendMap[defaultFeId].expectTuneStatuses = statuses;
+    frontendMap[defaultFeId].isSoftwareFe = true;
+    frontendMap[defaultFeId].canConnectToCiCam = true;
+    frontendMap[defaultFeId].ciCamId = 0;
+    FrontendDvbtSettings dvbt;
+    dvbt.transmissionMode = FrontendDvbtTransmissionMode::MODE_8K_E;
+    frontendMap[defaultFeId].settings.set<FrontendSettings::Tag::dvbt>(dvbt);
+    // Read customized config
+    TunerTestingConfigAidlReader1_0::readFrontendConfig1_0(frontendMap);
+};
+
+inline void initFilterConfig() {
+    // The test will use the internal default filter when default filter is connected to any
+    // data flow without overriding in the xml config.
+    string defaultAudioFilterId = "FILTER_AUDIO_DEFAULT";
+    string defaultVideoFilterId = "FILTER_VIDEO_DEFAULT";
+
+    filterMap[defaultVideoFilterId].type.mainType = DemuxFilterMainType::TS;
+    filterMap[defaultVideoFilterId].type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+            DemuxTsFilterType::VIDEO);
+    filterMap[defaultVideoFilterId].bufferSize = FMQ_SIZE_16M;
+    filterMap[defaultVideoFilterId].settings =
+            DemuxFilterSettings::make<DemuxFilterSettings::Tag::ts>();
+    filterMap[defaultVideoFilterId].settings.get<DemuxFilterSettings::Tag::ts>().tpid = 256;
+    DemuxFilterAvSettings video;
+    video.isPassthrough = false;
+    filterMap[defaultVideoFilterId]
+            .settings.get<DemuxFilterSettings::Tag::ts>()
+            .filterSettings.set<DemuxTsFilterSettingsFilterSettings::Tag::av>(video);
+    filterMap[defaultVideoFilterId].monitorEventTypes =
+            static_cast<int32_t>(DemuxFilterMonitorEventType::SCRAMBLING_STATUS) |
+            static_cast<int32_t>(DemuxFilterMonitorEventType::IP_CID_CHANGE);
+    filterMap[defaultVideoFilterId].streamType.set<AvStreamType::Tag::video>(
+            VideoStreamType::MPEG1);
+
+    filterMap[defaultAudioFilterId].type.mainType = DemuxFilterMainType::TS;
+    filterMap[defaultAudioFilterId].type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+            DemuxTsFilterType::AUDIO);
+    filterMap[defaultAudioFilterId].bufferSize = FMQ_SIZE_16M;
+    filterMap[defaultAudioFilterId].settings =
+            DemuxFilterSettings::make<DemuxFilterSettings::Tag::ts>();
+    filterMap[defaultAudioFilterId].settings.get<DemuxFilterSettings::Tag::ts>().tpid = 256;
+    DemuxFilterAvSettings audio;
+    audio.isPassthrough = false;
+    filterMap[defaultAudioFilterId]
+            .settings.get<DemuxFilterSettings::Tag::ts>()
+            .filterSettings.set<DemuxTsFilterSettingsFilterSettings::Tag::av>(audio);
+    filterMap[defaultAudioFilterId].monitorEventTypes =
+            static_cast<int32_t>(DemuxFilterMonitorEventType::SCRAMBLING_STATUS) |
+            static_cast<int32_t>(DemuxFilterMonitorEventType::IP_CID_CHANGE);
+    filterMap[defaultAudioFilterId].streamType.set<AvStreamType::Tag::audio>(AudioStreamType::MP3);
+    // Read customized config
+    TunerTestingConfigAidlReader1_0::readFilterConfig1_0(filterMap);
+};
+
+/** Config all the dvrs that would be used in the tests */
+inline void initDvrConfig() {
+    // Read customized config
+    TunerTestingConfigAidlReader1_0::readDvrConfig1_0(dvrMap);
+};
+
+/** Read the vendor configurations of which hardware to use for each test cases/data flows */
+inline void connectHardwaresToTestCases() {
+    TunerTestingConfigAidlReader1_0::connectLiveBroadcast(live);
+    TunerTestingConfigAidlReader1_0::connectScan(scan);
+    TunerTestingConfigAidlReader1_0::connectDvrRecord(record);
+};
+
+inline bool validateConnections() {
+    if (record.support && !record.hasFrontendConnection &&
+        record.dvrSourceId.compare(emptyHardwareId) == 0) {
+        ALOGW("[vts config] Record must support either a DVR source or a Frontend source.");
+        return false;
+    }
+    bool feIsValid = frontendMap.find(live.frontendId) != frontendMap.end() &&
+                     frontendMap.find(scan.frontendId) != frontendMap.end();
+    feIsValid &= record.support ? frontendMap.find(record.frontendId) != frontendMap.end() : true;
+
+    if (!feIsValid) {
+        ALOGW("[vts config] dynamic config fe connection is invalid.");
+        return false;
+    }
+
+    bool dvrIsValid = frontendMap[live.frontendId].isSoftwareFe
+                              ? dvrMap.find(live.dvrSoftwareFeId) != dvrMap.end()
+                              : true;
+
+    if (record.support) {
+        if (record.hasFrontendConnection) {
+            if (frontendMap[record.frontendId].isSoftwareFe) {
+                dvrIsValid &= dvrMap.find(record.dvrSoftwareFeId) != dvrMap.end();
+            }
+        } else {
+            dvrIsValid &= dvrMap.find(record.dvrSourceId) != dvrMap.end();
+        }
+        dvrIsValid &= dvrMap.find(record.dvrRecordId) != dvrMap.end();
+    }
+
+    if (!dvrIsValid) {
+        ALOGW("[vts config] dynamic config dvr connection is invalid.");
+        return false;
+    }
+
+    bool filterIsValid = filterMap.find(live.audioFilterId) != filterMap.end() &&
+                         filterMap.find(live.videoFilterId) != filterMap.end();
+    filterIsValid &=
+            record.support ? filterMap.find(record.recordFilterId) != filterMap.end() : true;
+
+    if (!filterIsValid) {
+        ALOGW("[vts config] dynamic config filter connection is invalid.");
+        return false;
+    }
+
+    return true;
+}
diff --git a/tv/tuner/config/OWNERS b/tv/tuner/config/OWNERS
index 1b3d095..bf2b609 100644
--- a/tv/tuner/config/OWNERS
+++ b/tv/tuner/config/OWNERS
@@ -1,4 +1,3 @@
-nchalko@google.com
-amyjojo@google.com
+hgchen@google.com
 shubang@google.com
 quxiangfang@google.com
diff --git a/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
new file mode 100644
index 0000000..b6cc5f8
--- /dev/null
+++ b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
@@ -0,0 +1,1015 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+#include <android_media_tuner_testing_configuration_V1_0.h>
+#include <android_media_tuner_testing_configuration_V1_0_enums.h>
+
+#include <aidl/android/hardware/tv/tuner/DataFormat.h>
+#include <aidl/android/hardware/tv/tuner/DemuxAlpFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterAvSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterMainType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterRecordSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSectionSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxIpAddress.h>
+#include <aidl/android/hardware/tv/tuner/DemuxIpFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxIpFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxMmtpFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxRecordScIndexType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxTlvFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxTsFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DvrSettings.h>
+#include <aidl/android/hardware/tv/tuner/DvrType.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbsSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtBandwidth.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtCoderate.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtConstellation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtGuardInterval.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtHierarchy.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtPlpMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtStandard.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendStatus.h>
+#include <aidl/android/hardware/tv/tuner/FrontendStatusType.h>
+#include <aidl/android/hardware/tv/tuner/FrontendType.h>
+#include <aidl/android/hardware/tv/tuner/LnbPosition.h>
+#include <aidl/android/hardware/tv/tuner/LnbTone.h>
+#include <aidl/android/hardware/tv/tuner/LnbVoltage.h>
+#include <aidl/android/hardware/tv/tuner/PlaybackSettings.h>
+#include <aidl/android/hardware/tv/tuner/RecordSettings.h>
+
+using namespace std;
+using namespace aidl::android::hardware::tv::tuner;
+using namespace android::media::tuner::testing::configuration::V1_0;
+
+const string emptyHardwareId = "";
+
+static string mConfigFilePath;
+
+#define PROVISION_STR                                      \
+    "{                                                   " \
+    "  \"id\": 21140844,                                 " \
+    "  \"name\": \"Test Title\",                         " \
+    "  \"lowercase_organization_name\": \"Android\",     " \
+    "  \"asset_key\": {                                  " \
+    "  \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\"  " \
+    "  },                                                " \
+    "  \"cas_type\": 1,                                  " \
+    "  \"track_types\": [ ]                              " \
+    "}                                                   "
+
+struct FrontendConfig {
+    bool isSoftwareFe;
+    FrontendType type;
+    bool canConnectToCiCam;
+    int32_t ciCamId;
+    FrontendSettings settings;
+    vector<FrontendStatusType> tuneStatusTypes;
+    vector<FrontendStatus> expectTuneStatuses;
+};
+
+struct FilterConfig {
+    int32_t bufferSize;
+    DemuxFilterType type;
+    DemuxFilterSettings settings;
+    bool getMqDesc;
+    AvStreamType streamType;
+    int32_t ipCid;
+    int32_t monitorEventTypes;
+    int timeDelayInMs = 0;
+    int dataDelayInBytes = 0;
+
+    bool operator<(const FilterConfig& /*c*/) const { return false; }
+};
+
+struct DvrConfig {
+    DvrType type;
+    int32_t bufferSize;
+    DvrSettings settings;
+    string playbackInputFile;
+};
+
+struct LnbConfig {
+    string name;
+    LnbVoltage voltage;
+    LnbTone tone;
+    LnbPosition position;
+};
+
+struct TimeFilterConfig {
+    int64_t timeStamp;
+};
+
+struct DescramblerConfig {
+    int32_t casSystemId;
+    string provisionStr;
+    vector<uint8_t> hidlPvtData;
+};
+
+struct LiveBroadcastHardwareConnections {
+    bool hasFrontendConnection;
+    string frontendId;
+    string dvrSoftwareFeId;
+    string audioFilterId;
+    string videoFilterId;
+    string sectionFilterId;
+    string ipFilterId;
+    string pcrFilterId;
+    /* list string of extra filters; */
+};
+
+struct ScanHardwareConnections {
+    bool hasFrontendConnection;
+    string frontendId;
+};
+
+struct DvrPlaybackHardwareConnections {
+    bool support;
+    string frontendId;
+    string dvrId;
+    string audioFilterId;
+    string videoFilterId;
+    string sectionFilterId;
+    /* list string of extra filters; */
+};
+
+struct DvrRecordHardwareConnections {
+    bool support;
+    bool hasFrontendConnection;
+    string frontendId;
+    string dvrRecordId;
+    string dvrSoftwareFeId;
+    string recordFilterId;
+    string dvrSourceId;
+};
+
+struct DescramblingHardwareConnections {
+    bool support;
+    bool hasFrontendConnection;
+    string frontendId;
+    string dvrSoftwareFeId;
+    string audioFilterId;
+    string videoFilterId;
+    string descramblerId;
+    string dvrSourceId;
+    /* list string of extra filters; */
+};
+
+struct LnbLiveHardwareConnections {
+    bool support;
+    string frontendId;
+    string audioFilterId;
+    string videoFilterId;
+    string lnbId;
+    vector<string> diseqcMsgs;
+    /* list string of extra filters; */
+};
+
+struct LnbRecordHardwareConnections {
+    bool support;
+    string frontendId;
+    string dvrRecordId;
+    string recordFilterId;
+    string lnbId;
+    vector<string> diseqcMsgs;
+    /* list string of extra filters; */
+};
+
+struct TimeFilterHardwareConnections {
+    bool support;
+    string timeFilterId;
+};
+
+struct TunerTestingConfigAidlReader1_0 {
+  public:
+    static void setConfigFilePath(string path) { mConfigFilePath = path; }
+
+    static bool checkConfigFileExists() {
+        auto res = read(mConfigFilePath.c_str());
+        if (res == nullopt) {
+            ALOGW("[ConfigReader] Couldn't read %s."
+                  "Please check tuner_testing_dynamic_configuration.xsd"
+                  "and sample_tuner_vts_config.xml for more details on how to config Tune VTS.",
+                  mConfigFilePath.c_str());
+        }
+        return (res != nullopt);
+    }
+
+    static TunerConfiguration getTunerConfig() { return *read(mConfigFilePath.c_str()); }
+
+    static DataFlowConfiguration getDataFlowConfiguration() {
+        return *getTunerConfig().getFirstDataFlowConfiguration();
+    }
+
+    static HardwareConfiguration getHardwareConfig() {
+        return *getTunerConfig().getFirstHardwareConfiguration();
+    }
+
+    static void readFrontendConfig1_0(map<string, FrontendConfig>& frontendMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasFrontends()) {
+            // TODO: b/182519645 complete the tune status config
+            vector<FrontendStatusType> types;
+            vector<FrontendStatus> statuses;
+
+            types.push_back(FrontendStatusType::DEMOD_LOCK);
+            types.push_back(FrontendStatusType::UEC);
+            types.push_back(FrontendStatusType::IS_MISO);
+
+            FrontendStatus status;
+            status.set<FrontendStatus::Tag::isDemodLocked>(true);
+            statuses.push_back(status);
+            status.set<FrontendStatus::Tag::uec>(4);
+            statuses.push_back(status);
+            status.set<FrontendStatus::Tag::isMiso>(true);
+            statuses.push_back(status);
+
+            auto frontends = *hardwareConfig.getFirstFrontends();
+            for (auto feConfig : frontends.getFrontend()) {
+                string id = feConfig.getId();
+                if (id.compare(string("FE_DEFAULT")) == 0) {
+                    // overrid default
+                    frontendMap.erase(string("FE_DEFAULT"));
+                }
+                FrontendType type;
+                switch (feConfig.getType()) {
+                    case FrontendTypeEnum::UNDEFINED:
+                        type = FrontendType::UNDEFINED;
+                        break;
+                    // TODO: b/182519645 finish all other frontend settings
+                    case FrontendTypeEnum::ANALOG:
+                        type = FrontendType::ANALOG;
+                        break;
+                    case FrontendTypeEnum::ATSC:
+                        type = FrontendType::ATSC;
+                        break;
+                    case FrontendTypeEnum::ATSC3:
+                        type = FrontendType::ATSC3;
+                        break;
+                    case FrontendTypeEnum::DVBC:
+                        type = FrontendType::DVBC;
+                        break;
+                    case FrontendTypeEnum::DVBS:
+                        type = FrontendType::DVBS;
+                        frontendMap[id].settings.set<FrontendSettings::Tag::dvbs>(
+                                readDvbsFrontendSettings(feConfig));
+                        break;
+                    case FrontendTypeEnum::DVBT: {
+                        type = FrontendType::DVBT;
+                        frontendMap[id].settings.set<FrontendSettings::Tag::dvbt>(
+                                readDvbtFrontendSettings(feConfig));
+                        break;
+                    }
+                    case FrontendTypeEnum::ISDBS:
+                        type = FrontendType::ISDBS;
+                        break;
+                    case FrontendTypeEnum::ISDBS3:
+                        type = FrontendType::ISDBS3;
+                        break;
+                    case FrontendTypeEnum::ISDBT:
+                        type = FrontendType::ISDBT;
+                        break;
+                    case FrontendTypeEnum::DTMB:
+                        type = FrontendType::DTMB;
+                        break;
+                    case FrontendTypeEnum::UNKNOWN:
+                        ALOGW("[ConfigReader] invalid frontend type");
+                        return;
+                    default:
+                        ALOGW("[ConfigReader] fe already handled in 1_0 reader.");
+                        break;
+                }
+                frontendMap[id].type = type;
+                frontendMap[id].isSoftwareFe = feConfig.getIsSoftwareFrontend();
+                // TODO: b/182519645 complete the tune status config
+                frontendMap[id].tuneStatusTypes = types;
+                frontendMap[id].expectTuneStatuses = statuses;
+                getCiCamInfo(feConfig, frontendMap[id].canConnectToCiCam, frontendMap[id].ciCamId);
+            }
+        }
+    }
+
+    static void readFilterConfig1_0(map<string, FilterConfig>& filterMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasFilters()) {
+            auto filters = *hardwareConfig.getFirstFilters();
+            for (auto filterConfig : filters.getFilter()) {
+                string id = filterConfig.getId();
+                if (id.compare(string("FILTER_AUDIO_DEFAULT")) == 0) {
+                    // overrid default
+                    filterMap.erase(string("FILTER_AUDIO_DEFAULT"));
+                }
+                if (id.compare(string("FILTER_VIDEO_DEFAULT")) == 0) {
+                    // overrid default
+                    filterMap.erase(string("FILTER_VIDEO_DEFAULT"));
+                }
+
+                DemuxFilterType type;
+                DemuxFilterSettings settings;
+                if (!readFilterTypeAndSettings(filterConfig, type, settings)) {
+                    ALOGW("[ConfigReader] invalid filter type");
+                    return;
+                }
+                filterMap[id].type = type;
+                filterMap[id].bufferSize = filterConfig.getBufferSize();
+                filterMap[id].getMqDesc = filterConfig.getUseFMQ();
+                filterMap[id].settings = settings;
+
+                if (filterConfig.hasMonitorEventTypes()) {
+                    filterMap[id].monitorEventTypes = (int32_t)filterConfig.getMonitorEventTypes();
+                }
+                if (filterConfig.hasTimeDelayInMs()) {
+                    filterMap[id].timeDelayInMs = filterConfig.getTimeDelayInMs();
+                }
+                if (filterConfig.hasDataDelayInBytes()) {
+                    filterMap[id].dataDelayInBytes = filterConfig.getDataDelayInBytes();
+                }
+                if (filterConfig.hasAvFilterSettings_optional()) {
+                    auto av = filterConfig.getFirstAvFilterSettings_optional();
+                    if (av->hasAudioStreamType_optional()) {
+                        filterMap[id].streamType.set<AvStreamType::Tag::audio>(
+                                static_cast<AudioStreamType>(av->getAudioStreamType_optional()));
+                    }
+                    if (av->hasVideoStreamType_optional()) {
+                        filterMap[id].streamType.set<AvStreamType::Tag::video>(
+                                static_cast<VideoStreamType>(av->getVideoStreamType_optional()));
+                    }
+                }
+                if (filterConfig.hasIpFilterConfig_optional()) {
+                    auto ip = filterConfig.getFirstIpFilterConfig_optional();
+                    if (ip->hasIpCid()) {
+                        filterMap[id].ipCid = ip->getIpCid();
+                    }
+                }
+            }
+        }
+    }
+
+    static void readDvrConfig1_0(map<string, DvrConfig>& dvrMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasDvrs()) {
+            auto dvrs = *hardwareConfig.getFirstDvrs();
+            for (auto dvrConfig : dvrs.getDvr()) {
+                string id = dvrConfig.getId();
+                DvrType type;
+                switch (dvrConfig.getType()) {
+                    case DvrTypeEnum::PLAYBACK:
+                        type = DvrType::PLAYBACK;
+                        dvrMap[id].settings.set<DvrSettings::Tag::playback>(
+                                readPlaybackSettings(dvrConfig));
+                        break;
+                    case DvrTypeEnum::RECORD:
+                        type = DvrType::RECORD;
+                        dvrMap[id].settings.set<DvrSettings::Tag::record>(
+                                readRecordSettings(dvrConfig));
+                        break;
+                    case DvrTypeEnum::UNKNOWN:
+                        ALOGW("[ConfigReader] invalid DVR type");
+                        return;
+                }
+                dvrMap[id].type = type;
+                dvrMap[id].bufferSize = static_cast<int32_t>(dvrConfig.getBufferSize());
+                if (dvrConfig.hasInputFilePath()) {
+                    dvrMap[id].playbackInputFile = dvrConfig.getInputFilePath();
+                }
+            }
+        }
+    }
+
+    static void readLnbConfig1_0(map<string, LnbConfig>& lnbMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasLnbs()) {
+            auto lnbs = *hardwareConfig.getFirstLnbs();
+            for (auto lnbConfig : lnbs.getLnb()) {
+                string id = lnbConfig.getId();
+                if (lnbConfig.hasName()) {
+                    lnbMap[id].name = lnbConfig.getName();
+                } else {
+                    lnbMap[id].name = emptyHardwareId;
+                }
+                lnbMap[id].voltage = static_cast<LnbVoltage>(lnbConfig.getVoltage());
+                lnbMap[id].tone = static_cast<LnbTone>(lnbConfig.getTone());
+                lnbMap[id].position = static_cast<LnbPosition>(lnbConfig.getPosition());
+            }
+        }
+    }
+
+    static void readDescramblerConfig1_0(map<string, DescramblerConfig>& descramblerMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasDescramblers()) {
+            auto descramblers = *hardwareConfig.getFirstDescramblers();
+            for (auto descramblerConfig : descramblers.getDescrambler()) {
+                string id = descramblerConfig.getId();
+                descramblerMap[id].casSystemId =
+                        static_cast<int32_t>(descramblerConfig.getCasSystemId());
+                if (descramblerConfig.hasProvisionStr()) {
+                    descramblerMap[id].provisionStr = descramblerConfig.getProvisionStr();
+                } else {
+                    descramblerMap[id].provisionStr = PROVISION_STR;
+                }
+                if (descramblerConfig.hasSesstionPrivatData()) {
+                    auto privateData = descramblerConfig.getSesstionPrivatData();
+                    int size = privateData.size();
+                    descramblerMap[id].hidlPvtData.resize(size);
+                    memcpy(descramblerMap[id].hidlPvtData.data(), privateData.data(), size);
+                } else {
+                    descramblerMap[id].hidlPvtData.resize(256);
+                }
+            }
+        }
+    }
+
+    static void readDiseqcMessages(map<string, vector<uint8_t>>& diseqcMsgMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasDiseqcMessages()) {
+            auto msgs = *hardwareConfig.getFirstDiseqcMessages();
+            for (auto msgConfig : msgs.getDiseqcMessage()) {
+                string name = msgConfig.getMsgName();
+                for (uint8_t atom : msgConfig.getMsgBody()) {
+                    diseqcMsgMap[name].push_back(atom);
+                }
+            }
+        }
+    }
+
+    static void readTimeFilterConfig1_0(map<string, TimeFilterConfig>& timeFilterMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasTimeFilters()) {
+            auto timeFilters = *hardwareConfig.getFirstTimeFilters();
+            for (auto timeFilterConfig : timeFilters.getTimeFilter()) {
+                string id = timeFilterConfig.getId();
+                timeFilterMap[id].timeStamp = static_cast<int64_t>(timeFilterConfig.getTimeStamp());
+            }
+        }
+    }
+
+    static void connectLiveBroadcast(LiveBroadcastHardwareConnections& live) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasClearLiveBroadcast()) {
+            live.hasFrontendConnection = true;
+        } else {
+            live.hasFrontendConnection = false;
+            return;
+        }
+        auto liveConfig = *dataFlow.getFirstClearLiveBroadcast();
+        live.frontendId = liveConfig.getFrontendConnection();
+
+        live.audioFilterId = liveConfig.getAudioFilterConnection();
+        live.videoFilterId = liveConfig.getVideoFilterConnection();
+        if (liveConfig.hasPcrFilterConnection()) {
+            live.pcrFilterId = liveConfig.getPcrFilterConnection();
+        } else {
+            live.pcrFilterId = emptyHardwareId;
+        }
+        if (liveConfig.hasSectionFilterConnection()) {
+            live.sectionFilterId = liveConfig.getSectionFilterConnection();
+        } else {
+            live.sectionFilterId = emptyHardwareId;
+        }
+        if (liveConfig.hasDvrSoftwareFeConnection()) {
+            live.dvrSoftwareFeId = liveConfig.getDvrSoftwareFeConnection();
+        }
+        if (liveConfig.hasIpFilterConnection()) {
+            live.ipFilterId = liveConfig.getIpFilterConnection();
+        } else {
+            live.ipFilterId = emptyHardwareId;
+        }
+    }
+
+    static void connectScan(ScanHardwareConnections& scan) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasScan()) {
+            scan.hasFrontendConnection = true;
+        } else {
+            scan.hasFrontendConnection = false;
+            return;
+        }
+        auto scanConfig = *dataFlow.getFirstScan();
+        scan.frontendId = scanConfig.getFrontendConnection();
+    }
+
+    static void connectDvrPlayback(DvrPlaybackHardwareConnections& playback) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasDvrPlayback()) {
+            playback.support = true;
+        } else {
+            playback.support = false;
+            return;
+        }
+        auto playbackConfig = *dataFlow.getFirstDvrPlayback();
+        playback.dvrId = playbackConfig.getDvrConnection();
+        playback.audioFilterId = playbackConfig.getAudioFilterConnection();
+        playback.videoFilterId = playbackConfig.getVideoFilterConnection();
+        if (playbackConfig.hasSectionFilterConnection()) {
+            playback.sectionFilterId = playbackConfig.getSectionFilterConnection();
+        } else {
+            playback.sectionFilterId = emptyHardwareId;
+        }
+    }
+
+    static void connectDvrRecord(DvrRecordHardwareConnections& record) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasDvrRecord()) {
+            record.support = true;
+        } else {
+            record.support = false;
+            return;
+        }
+        auto recordConfig = *dataFlow.getFirstDvrRecord();
+        record.recordFilterId = recordConfig.getRecordFilterConnection();
+        record.dvrRecordId = recordConfig.getDvrRecordConnection();
+        if (recordConfig.hasDvrSoftwareFeConnection()) {
+            record.dvrSoftwareFeId = recordConfig.getDvrSoftwareFeConnection();
+        }
+        if (recordConfig.getHasFrontendConnection()) {
+            record.hasFrontendConnection = true;
+            record.dvrSourceId = emptyHardwareId;
+            record.frontendId = recordConfig.getFrontendConnection();
+        } else {
+            record.hasFrontendConnection = false;
+            record.dvrSourceId = recordConfig.getDvrSourceConnection();
+        }
+    }
+
+    static void connectDescrambling(DescramblingHardwareConnections& descrambling) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasDescrambling()) {
+            descrambling.support = true;
+        } else {
+            descrambling.support = false;
+            return;
+        }
+        auto descConfig = *dataFlow.getFirstDescrambling();
+        descrambling.descramblerId = descConfig.getDescramblerConnection();
+        descrambling.audioFilterId = descConfig.getAudioFilterConnection();
+        descrambling.videoFilterId = descConfig.getVideoFilterConnection();
+        if (descConfig.hasDvrSoftwareFeConnection()) {
+            descrambling.dvrSoftwareFeId = descConfig.getDvrSoftwareFeConnection();
+        }
+        if (descConfig.getHasFrontendConnection()) {
+            descrambling.hasFrontendConnection = true;
+            descrambling.dvrSourceId = emptyHardwareId;
+            descrambling.frontendId = descConfig.getFrontendConnection();
+        } else {
+            descrambling.hasFrontendConnection = false;
+            descrambling.dvrSourceId = descConfig.getDvrSourceConnection();
+        }
+    }
+
+    static void connectLnbLive(LnbLiveHardwareConnections& lnbLive) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasLnbLive()) {
+            lnbLive.support = true;
+        } else {
+            lnbLive.support = false;
+            return;
+        }
+        auto lnbLiveConfig = *dataFlow.getFirstLnbLive();
+        lnbLive.frontendId = lnbLiveConfig.getFrontendConnection();
+        lnbLive.audioFilterId = lnbLiveConfig.getAudioFilterConnection();
+        lnbLive.videoFilterId = lnbLiveConfig.getVideoFilterConnection();
+        lnbLive.lnbId = lnbLiveConfig.getLnbConnection();
+        if (lnbLiveConfig.hasDiseqcMsgSender()) {
+            for (auto msgName : lnbLiveConfig.getDiseqcMsgSender()) {
+                lnbLive.diseqcMsgs.push_back(msgName);
+            }
+        }
+    }
+
+    static void connectLnbRecord(LnbRecordHardwareConnections& lnbRecord) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasLnbRecord()) {
+            lnbRecord.support = true;
+        } else {
+            lnbRecord.support = false;
+            return;
+        }
+        auto lnbRecordConfig = *dataFlow.getFirstLnbRecord();
+        lnbRecord.frontendId = lnbRecordConfig.getFrontendConnection();
+        lnbRecord.recordFilterId = lnbRecordConfig.getRecordFilterConnection();
+        lnbRecord.dvrRecordId = lnbRecordConfig.getDvrRecordConnection();
+        lnbRecord.lnbId = lnbRecordConfig.getLnbConnection();
+        if (lnbRecordConfig.hasDiseqcMsgSender()) {
+            for (auto msgName : lnbRecordConfig.getDiseqcMsgSender()) {
+                lnbRecord.diseqcMsgs.push_back(msgName);
+            }
+        }
+    }
+
+    static void connectTimeFilter(TimeFilterHardwareConnections& timeFilter) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasTimeFilter()) {
+            timeFilter.support = true;
+        } else {
+            timeFilter.support = false;
+            return;
+        }
+        auto timeFilterConfig = *dataFlow.getFirstTimeFilter();
+        timeFilter.timeFilterId = timeFilterConfig.getTimeFilterConnection();
+    }
+
+  private:
+    static FrontendDvbtSettings readDvbtFrontendSettings(Frontend feConfig) {
+        ALOGW("[ConfigReader] fe type is dvbt");
+        FrontendDvbtSettings dvbtSettings{
+                .frequency = (int64_t)feConfig.getFrequency(),
+        };
+        if (feConfig.hasEndFrequency()) {
+            dvbtSettings.endFrequency = (int64_t)feConfig.getEndFrequency();
+        }
+        if (!feConfig.hasDvbtFrontendSettings_optional()) {
+            ALOGW("[ConfigReader] no more dvbt settings");
+            return dvbtSettings;
+        }
+        auto dvbt = feConfig.getFirstDvbtFrontendSettings_optional();
+        int32_t trans = static_cast<int32_t>(dvbt->getTransmissionMode());
+        dvbtSettings.transmissionMode = static_cast<FrontendDvbtTransmissionMode>(trans);
+        dvbtSettings.bandwidth = static_cast<FrontendDvbtBandwidth>(dvbt->getBandwidth());
+        dvbtSettings.isHighPriority = dvbt->getIsHighPriority();
+        dvbtSettings.hierarchy = static_cast<FrontendDvbtHierarchy>(dvbt->getHierarchy());
+        dvbtSettings.hpCoderate = static_cast<FrontendDvbtCoderate>(dvbt->getHpCoderate());
+        dvbtSettings.lpCoderate = static_cast<FrontendDvbtCoderate>(dvbt->getLpCoderate());
+        dvbtSettings.guardInterval =
+                static_cast<FrontendDvbtGuardInterval>(dvbt->getGuardInterval());
+        dvbtSettings.standard = static_cast<FrontendDvbtStandard>(dvbt->getStandard());
+        dvbtSettings.isMiso = dvbt->getIsMiso();
+        dvbtSettings.plpMode = static_cast<FrontendDvbtPlpMode>(dvbt->getPlpMode());
+        dvbtSettings.plpId = dvbt->getPlpId();
+        dvbtSettings.plpGroupId = dvbt->getPlpGroupId();
+        if (dvbt->hasConstellation()) {
+            dvbtSettings.constellation =
+                    static_cast<FrontendDvbtConstellation>(dvbt->getConstellation());
+        }
+        return dvbtSettings;
+    }
+
+    static FrontendDvbsSettings readDvbsFrontendSettings(Frontend feConfig) {
+        ALOGW("[ConfigReader] fe type is dvbs");
+        FrontendDvbsSettings dvbsSettings{
+                .frequency = (int64_t)feConfig.getFrequency(),
+        };
+        if (feConfig.hasEndFrequency()) {
+            dvbsSettings.endFrequency = (int64_t)feConfig.getEndFrequency();
+        }
+        if (!feConfig.hasDvbsFrontendSettings_optional()) {
+            ALOGW("[ConfigReader] no more dvbs settings");
+            return dvbsSettings;
+        }
+        dvbsSettings.symbolRate = static_cast<int32_t>(
+                feConfig.getFirstDvbsFrontendSettings_optional()->getSymbolRate());
+        dvbsSettings.inputStreamId = static_cast<int32_t>(
+                feConfig.getFirstDvbsFrontendSettings_optional()->getInputStreamId());
+        auto dvbs = feConfig.getFirstDvbsFrontendSettings_optional();
+        if (dvbs->hasScanType()) {
+            dvbsSettings.scanType = static_cast<FrontendDvbsScanType>(dvbs->getScanType());
+        }
+        if (dvbs->hasIsDiseqcRxMessage()) {
+            dvbsSettings.isDiseqcRxMessage = dvbs->getIsDiseqcRxMessage();
+        }
+        return dvbsSettings;
+    }
+
+    static bool readFilterTypeAndSettings(Filter filterConfig, DemuxFilterType& type,
+                                          DemuxFilterSettings& settings) {
+        auto mainType = filterConfig.getMainType();
+        auto subType = filterConfig.getSubType();
+
+        switch (mainType) {
+            case FilterMainTypeEnum::TS: {
+                ALOGW("[ConfigReader] filter main type is ts");
+                type.mainType = DemuxFilterMainType::TS;
+                DemuxTsFilterSettings ts;
+                bool isTsSet = false;
+                switch (subType) {
+                    case FilterSubTypeEnum::UNDEFINED:
+                        type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+                                DemuxTsFilterType::UNDEFINED);
+                        break;
+                    case FilterSubTypeEnum::SECTION:
+                        type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+                                DemuxTsFilterType::SECTION);
+                        ts.filterSettings.set<DemuxTsFilterSettingsFilterSettings::Tag::section>(
+                                readSectionFilterSettings(filterConfig));
+                        isTsSet = true;
+                        break;
+                    case FilterSubTypeEnum::PES:
+                        // TODO: b/182519645 support all the filter settings
+                        type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+                                DemuxTsFilterType::PES);
+                        break;
+                    case FilterSubTypeEnum::TS:
+                        type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+                                DemuxTsFilterType::TS);
+                        ts.filterSettings.set<DemuxTsFilterSettingsFilterSettings::Tag::noinit>(
+                                true);
+                        isTsSet = true;
+                        break;
+                    case FilterSubTypeEnum::PCR:
+                        type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+                                DemuxTsFilterType::PCR);
+                        ts.filterSettings.set<DemuxTsFilterSettingsFilterSettings::Tag::noinit>(
+                                true);
+                        isTsSet = true;
+                        break;
+                    case FilterSubTypeEnum::TEMI:
+                        type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+                                DemuxTsFilterType::TEMI);
+                        ts.filterSettings.set<DemuxTsFilterSettingsFilterSettings::Tag::noinit>(
+                                true);
+                        isTsSet = true;
+                        break;
+                    case FilterSubTypeEnum::AUDIO:
+                        type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+                                DemuxTsFilterType::AUDIO);
+                        ts.filterSettings.set<DemuxTsFilterSettingsFilterSettings::Tag::av>(
+                                readAvFilterSettings(filterConfig));
+                        isTsSet = true;
+                        break;
+                    case FilterSubTypeEnum::VIDEO:
+                        type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+                                DemuxTsFilterType::VIDEO);
+                        ts.filterSettings.set<DemuxTsFilterSettingsFilterSettings::Tag::av>(
+                                readAvFilterSettings(filterConfig));
+                        isTsSet = true;
+                        break;
+                    case FilterSubTypeEnum::RECORD:
+                        type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+                                DemuxTsFilterType::RECORD);
+                        ts.filterSettings.set<DemuxTsFilterSettingsFilterSettings::Tag::record>(
+                                readRecordFilterSettings(filterConfig));
+                        isTsSet = true;
+                        break;
+                    default:
+                        ALOGW("[ConfigReader] ts subtype is not supported");
+                        return false;
+                }
+                if (filterConfig.hasPid()) {
+                    ts.tpid = static_cast<int32_t>(filterConfig.getPid());
+                    isTsSet = true;
+                }
+                if (isTsSet) {
+                    settings.set<DemuxFilterSettings::Tag::ts>(ts);
+                }
+                break;
+            }
+            case FilterMainTypeEnum::MMTP: {
+                ALOGW("[ConfigReader] filter main type is mmtp");
+                type.mainType = DemuxFilterMainType::MMTP;
+                DemuxMmtpFilterSettings mmtp;
+                bool isMmtpSet = false;
+                switch (subType) {
+                    case FilterSubTypeEnum::UNDEFINED:
+                        type.subType.set<DemuxFilterSubType::Tag::mmtpFilterType>(
+                                DemuxMmtpFilterType::UNDEFINED);
+                        break;
+                    case FilterSubTypeEnum::SECTION:
+                        type.subType.set<DemuxFilterSubType::Tag::mmtpFilterType>(
+                                DemuxMmtpFilterType::SECTION);
+                        mmtp.filterSettings
+                                .set<DemuxMmtpFilterSettingsFilterSettings::Tag::section>(
+                                        readSectionFilterSettings(filterConfig));
+                        isMmtpSet = true;
+                        break;
+                    case FilterSubTypeEnum::PES:
+                        type.subType.set<DemuxFilterSubType::Tag::mmtpFilterType>(
+                                DemuxMmtpFilterType::PES);
+                        // TODO: b/182519645 support all the filter settings
+                        break;
+                    case FilterSubTypeEnum::MMTP:
+                        type.subType.set<DemuxFilterSubType::Tag::mmtpFilterType>(
+                                DemuxMmtpFilterType::MMTP);
+                        mmtp.filterSettings.set<DemuxMmtpFilterSettingsFilterSettings::Tag::noinit>(
+                                true);
+                        isMmtpSet = true;
+                        break;
+                    case FilterSubTypeEnum::AUDIO:
+                        type.subType.set<DemuxFilterSubType::Tag::mmtpFilterType>(
+                                DemuxMmtpFilterType::AUDIO);
+                        mmtp.filterSettings.set<DemuxMmtpFilterSettingsFilterSettings::Tag::av>(
+                                readAvFilterSettings(filterConfig));
+                        isMmtpSet = true;
+                        break;
+                    case FilterSubTypeEnum::VIDEO:
+                        type.subType.set<DemuxFilterSubType::Tag::mmtpFilterType>(
+                                DemuxMmtpFilterType::VIDEO);
+                        mmtp.filterSettings.set<DemuxMmtpFilterSettingsFilterSettings::Tag::av>(
+                                readAvFilterSettings(filterConfig));
+                        isMmtpSet = true;
+                        break;
+                    case FilterSubTypeEnum::RECORD:
+                        type.subType.set<DemuxFilterSubType::Tag::mmtpFilterType>(
+                                DemuxMmtpFilterType::RECORD);
+                        mmtp.filterSettings.set<DemuxMmtpFilterSettingsFilterSettings::Tag::record>(
+                                readRecordFilterSettings(filterConfig));
+                        isMmtpSet = true;
+                        break;
+                    case FilterSubTypeEnum::DOWNLOAD:
+                        type.subType.set<DemuxFilterSubType::Tag::mmtpFilterType>(
+                                DemuxMmtpFilterType::DOWNLOAD);
+                        // TODO: b/182519645 support all the filter settings
+                        break;
+                    default:
+                        ALOGW("[ConfigReader] mmtp subtype is not supported");
+                        return false;
+                }
+                if (filterConfig.hasPid()) {
+                    mmtp.mmtpPid = static_cast<int32_t>(filterConfig.getPid());
+                    isMmtpSet = true;
+                }
+                if (isMmtpSet) {
+                    settings.set<DemuxFilterSettings::Tag::mmtp>(mmtp);
+                }
+                break;
+            }
+            case FilterMainTypeEnum::IP: {
+                ALOGW("[ConfigReader] filter main type is ip");
+                type.mainType = DemuxFilterMainType::IP;
+                DemuxIpFilterSettings ip;
+                switch (subType) {
+                    case FilterSubTypeEnum::UNDEFINED:
+                        type.subType.set<DemuxFilterSubType::Tag::ipFilterType>(
+                                DemuxIpFilterType::UNDEFINED);
+                        break;
+                    case FilterSubTypeEnum::SECTION:
+                        type.subType.set<DemuxFilterSubType::Tag::ipFilterType>(
+                                DemuxIpFilterType::SECTION);
+                        ip.filterSettings.set<DemuxIpFilterSettingsFilterSettings::Tag::section>(
+                                readSectionFilterSettings(filterConfig));
+                        settings.set<DemuxFilterSettings::Tag::ip>(ip);
+                        break;
+                    case FilterSubTypeEnum::NTP:
+                        type.subType.set<DemuxFilterSubType::Tag::ipFilterType>(
+                                DemuxIpFilterType::NTP);
+                        ip.filterSettings.set<DemuxIpFilterSettingsFilterSettings::Tag::noinit>(
+                                true);
+                        settings.set<DemuxFilterSettings::Tag::ip>(ip);
+                        break;
+                    case FilterSubTypeEnum::IP: {
+                        ip.ipAddr = readIpAddress(filterConfig),
+                        ip.filterSettings
+                                .set<DemuxIpFilterSettingsFilterSettings::Tag::bPassthrough>(
+                                        readPassthroughSettings(filterConfig));
+                        settings.set<DemuxFilterSettings::Tag::ip>(ip);
+                        break;
+                    }
+                    case FilterSubTypeEnum::IP_PAYLOAD:
+                        type.subType.set<DemuxFilterSubType::Tag::ipFilterType>(
+                                DemuxIpFilterType::IP_PAYLOAD);
+                        ip.filterSettings.set<DemuxIpFilterSettingsFilterSettings::Tag::noinit>(
+                                true);
+                        settings.set<DemuxFilterSettings::Tag::ip>(ip);
+                        break;
+                    case FilterSubTypeEnum::PAYLOAD_THROUGH:
+                        type.subType.set<DemuxFilterSubType::Tag::ipFilterType>(
+                                DemuxIpFilterType::PAYLOAD_THROUGH);
+                        ip.filterSettings.set<DemuxIpFilterSettingsFilterSettings::Tag::noinit>(
+                                true);
+                        settings.set<DemuxFilterSettings::Tag::ip>(ip);
+                        break;
+                    default:
+                        ALOGW("[ConfigReader] mmtp subtype is not supported");
+                        return false;
+                }
+                break;
+            }
+            default:
+                // TODO: b/182519645 support all the filter configs
+                ALOGW("[ConfigReader] filter main type is not supported in dynamic config");
+                return false;
+        }
+        return true;
+    }
+
+    static DemuxIpAddress readIpAddress(Filter filterConfig) {
+        DemuxIpAddress ipAddress;
+        vector<uint8_t> data;
+        if (!filterConfig.hasIpFilterConfig_optional()) {
+            return ipAddress;
+        }
+        auto ipFilterConfig = filterConfig.getFirstIpFilterConfig_optional();
+        if (ipFilterConfig->hasSrcPort()) {
+            ipAddress.srcPort = ipFilterConfig->getSrcPort();
+        }
+        if (ipFilterConfig->hasDestPort()) {
+            ipAddress.dstPort = ipFilterConfig->getDestPort();
+        }
+        if (ipFilterConfig->getFirstSrcIpAddress()->getIsIpV4()) {
+            data.resize(4);
+            memcpy(data.data(), ipFilterConfig->getFirstSrcIpAddress()->getIp().data(), 4);
+            ipAddress.srcIpAddress.set<DemuxIpAddressIpAddress::Tag::v4>(data);
+        } else {
+            data.resize(6);
+            memcpy(data.data(), ipFilterConfig->getFirstSrcIpAddress()->getIp().data(), 6);
+            ipAddress.srcIpAddress.set<DemuxIpAddressIpAddress::Tag::v6>(data);
+        }
+        if (ipFilterConfig->getFirstDestIpAddress()->getIsIpV4()) {
+            data.resize(4);
+            memcpy(data.data(), ipFilterConfig->getFirstDestIpAddress()->getIp().data(), 4);
+            ipAddress.dstIpAddress.set<DemuxIpAddressIpAddress::Tag::v4>(data);
+        } else {
+            data.resize(6);
+            memcpy(data.data(), ipFilterConfig->getFirstDestIpAddress()->getIp().data(), 6);
+            ipAddress.dstIpAddress.set<DemuxIpAddressIpAddress::Tag::v6>(data);
+        }
+        return ipAddress;
+    }
+
+    static bool readPassthroughSettings(Filter filterConfig) {
+        if (!filterConfig.hasIpFilterConfig_optional()) {
+            return false;
+        }
+        auto ipFilterConfig = filterConfig.getFirstIpFilterConfig_optional();
+        if (ipFilterConfig->hasDataPassthrough()) {
+            return ipFilterConfig->getDataPassthrough();
+        }
+        return false;
+    }
+
+    static DemuxFilterSectionSettings readSectionFilterSettings(Filter filterConfig) {
+        DemuxFilterSectionSettings settings;
+        if (!filterConfig.hasSectionFilterSettings_optional()) {
+            return settings;
+        }
+        auto section = filterConfig.getFirstSectionFilterSettings_optional();
+        settings.isCheckCrc = section->getIsCheckCrc();
+        settings.isRepeat = section->getIsRepeat();
+        settings.isRaw = section->getIsRaw();
+        return settings;
+    }
+
+    static DemuxFilterAvSettings readAvFilterSettings(Filter filterConfig) {
+        DemuxFilterAvSettings settings;
+        if (!filterConfig.hasAvFilterSettings_optional()) {
+            return settings;
+        }
+        auto av = filterConfig.getFirstAvFilterSettings_optional();
+        settings.isPassthrough = av->getIsPassthrough();
+        settings.isSecureMemory = av->getIsSecureMemory();
+        return settings;
+    }
+
+    static DemuxFilterRecordSettings readRecordFilterSettings(Filter filterConfig) {
+        DemuxFilterRecordSettings settings;
+        if (!filterConfig.hasRecordFilterSettings_optional()) {
+            return settings;
+        }
+        auto record = filterConfig.getFirstRecordFilterSettings_optional();
+        settings.tsIndexMask = record->getTsIndexMask();
+        settings.scIndexType = static_cast<DemuxRecordScIndexType>(record->getScIndexType());
+        return settings;
+    }
+
+    static PlaybackSettings readPlaybackSettings(Dvr dvrConfig) {
+        ALOGW("[ConfigReader] dvr type is playback");
+        PlaybackSettings playbackSettings{
+                .statusMask = static_cast<int8_t>(dvrConfig.getStatusMask()),
+                .lowThreshold = static_cast<int64_t>(dvrConfig.getLowThreshold()),
+                .highThreshold = static_cast<int64_t>(dvrConfig.getHighThreshold()),
+                .dataFormat = static_cast<DataFormat>(dvrConfig.getDataFormat()),
+                .packetSize = static_cast<int64_t>(dvrConfig.getPacketSize()),
+        };
+        return playbackSettings;
+    }
+
+    static RecordSettings readRecordSettings(Dvr dvrConfig) {
+        ALOGW("[ConfigReader] dvr type is record");
+        RecordSettings recordSettings{
+                .statusMask = static_cast<int8_t>(dvrConfig.getStatusMask()),
+                .lowThreshold = static_cast<int64_t>(dvrConfig.getLowThreshold()),
+                .highThreshold = static_cast<int64_t>(dvrConfig.getHighThreshold()),
+                .dataFormat = static_cast<DataFormat>(dvrConfig.getDataFormat()),
+                .packetSize = static_cast<int64_t>(dvrConfig.getPacketSize()),
+        };
+        return recordSettings;
+    }
+
+    static void getCiCamInfo(Frontend feConfig, bool& canConnectToCiCam, int32_t& ciCamId) {
+        if (!feConfig.hasConnectToCicamId()) {
+            canConnectToCiCam = false;
+            ciCamId = -1;
+            return;
+        }
+        canConnectToCiCam = true;
+        ciCamId = static_cast<int32_t>(feConfig.getConnectToCicamId());
+    }
+};
diff --git a/tv/tuner/config/TunerTestingConfigReaderV1_1.h b/tv/tuner/config/TunerTestingConfigReaderV1_1.h
index 13d5303..c87980d 100644
--- a/tv/tuner/config/TunerTestingConfigReaderV1_1.h
+++ b/tv/tuner/config/TunerTestingConfigReaderV1_1.h
@@ -145,6 +145,7 @@
         if (!feConfig.hasConnectToCicamId()) {
             canConnectToCiCam = false;
             ciCamId = -1;
+            return;
         }
         canConnectToCiCam = true;
         ciCamId = static_cast<uint32_t>(feConfig.getConnectToCicamId());
diff --git a/tv/tuner/config/api/current.txt b/tv/tuner/config/api/current.txt
index d026bf9..db1d076 100644
--- a/tv/tuner/config/api/current.txt
+++ b/tv/tuner/config/api/current.txt
@@ -5,9 +5,11 @@
     ctor public AvFilterSettings();
     method @Nullable public short getAudioStreamType_optional();
     method @Nullable public boolean getIsPassthrough();
+    method @Nullable public boolean getIsSecureMemory();
     method @Nullable public short getVideoStreamType_optional();
     method public void setAudioStreamType_optional(@Nullable short);
     method public void setIsPassthrough(@Nullable boolean);
+    method public void setIsSecureMemory(@Nullable boolean);
     method public void setVideoStreamType_optional(@Nullable short);
   }
 
@@ -254,6 +256,7 @@
     ctor public Filter();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.AvFilterSettings getAvFilterSettings_optional();
     method @Nullable public java.math.BigInteger getBufferSize();
+    method @Nullable public java.math.BigInteger getDataDelayInBytes();
     method @Nullable public String getId();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.IpFilterConfig getIpFilterConfig_optional();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum getMainType();
@@ -262,9 +265,11 @@
     method @Nullable public android.media.tuner.testing.configuration.V1_0.RecordFilterSettings getRecordFilterSettings_optional();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.SectionFilterSettings getSectionFilterSettings_optional();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum getSubType();
+    method @Nullable public java.math.BigInteger getTimeDelayInMs();
     method @Nullable public boolean getUseFMQ();
     method public void setAvFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.AvFilterSettings);
     method public void setBufferSize(@Nullable java.math.BigInteger);
+    method public void setDataDelayInBytes(@Nullable java.math.BigInteger);
     method public void setId(@Nullable String);
     method public void setIpFilterConfig_optional(@Nullable android.media.tuner.testing.configuration.V1_0.IpFilterConfig);
     method public void setMainType(@Nullable android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum);
@@ -273,6 +278,7 @@
     method public void setRecordFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.RecordFilterSettings);
     method public void setSectionFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.SectionFilterSettings);
     method public void setSubType(@Nullable android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum);
+    method public void setTimeDelayInMs(@Nullable java.math.BigInteger);
     method public void setUseFMQ(@Nullable boolean);
   }
 
diff --git a/tv/tuner/config/sample_tuner_vts_config_1_0.xml b/tv/tuner/config/sample_tuner_vts_config_1_0.xml
index 347e984..e880bcd 100644
--- a/tv/tuner/config/sample_tuner_vts_config_1_0.xml
+++ b/tv/tuner/config/sample_tuner_vts_config_1_0.xml
@@ -53,14 +53,14 @@
         -->
         <frontends>
             <frontend id="FE_DEFAULT" type="DVBT" isSoftwareFrontend="true"
-                      connectToCicamId="0" frequency="578000" endFrequency="800000">
+                      connectToCicamId="0" frequency="578000000" endFrequency="800000000">
                 <dvbtFrontendSettings bandwidth="8" transmissionMode="1" isHighPriority="1"
                                       constellation="1" hierarchy="1" hpCoderate="1" lpCoderate="1"
                                       guardInterval="1" standard="1" isMiso="0" plpMode="1"
                                       plpId="0" plpGroupId="0"/>
             </frontend>
             <frontend id="FE_DVBS_0" type="DVBS" isSoftwareFrontend="true"
-                      connectToCicamId="0" frequency="578000" endFrequency="800000">
+                      connectToCicamId="0" frequency="578000000" endFrequency="800000000">
             </frontend>
         </frontends>
         <!-- Filter section:
diff --git a/tv/tuner/config/sample_tuner_vts_config_1_1.xml b/tv/tuner/config/sample_tuner_vts_config_1_1.xml
index 8c99207..55ce0ec 100644
--- a/tv/tuner/config/sample_tuner_vts_config_1_1.xml
+++ b/tv/tuner/config/sample_tuner_vts_config_1_1.xml
@@ -53,11 +53,11 @@
         -->
         <frontends>
             <frontend id="FE_DEFAULT" type="DVBT" isSoftwareFrontend="true"
-                      connectToCicamId="0" frequency="578000" endFrequency="800000">
+                      connectToCicamId="0" frequency="578000000" endFrequency="800000000">
                 <dvbtFrontendSettings bandwidth="8" transmissionMode="128" isHighPriority="1"/>
             </frontend>
             <frontend id="FE_DVBS_0" type="DVBS" isSoftwareFrontend="true"
-                      connectToCicamId="0" frequency="578000" endFrequency="800000">
+                      connectToCicamId="0" frequency="578000000" endFrequency="800000000">
             </frontend>
         </frontends>
         <!-- Filter section:
diff --git a/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml b/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
new file mode 100644
index 0000000..da77200
--- /dev/null
+++ b/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- The Sample Tuner Testing Configuration.
+    Name the customized xml with "tuner_vts_config.xml" and push into the device
+    "/vendor/etc" path. Please use "tuner_testing_dynamic_configuration.xsd" to verify the xml.
+    The version section contains a “version” tag in the form “major.minor” e.g. version=”1.0”
+    This shows the tuner dynamic configuration version. -->
+<TunerConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <!-- Hardware Configuration section contains the configurations of all the hardwares
+        that would be used in the tests. In the "dataFlowConfiguration" section, each data flow
+        under test has its required/optional hardwares. The ids configured in the
+        "dataFlowConfiguration" would be used to connect the hardware to each data flow test. -->
+    <hardwareConfiguration>
+        <!-- Frontends section:
+            This section contains configurations of all the frontends that would be used
+                in the tests.
+                - This section is optional and can be skipped to use the default fe settings.
+                - The default settings can be found in the sample_tuner_vts_configurations.xml.
+                - The users can also override the default frontend settings using id="FE_DEFAULT".
+                - The users can configure 1 or more frontend elements in the frontends sections.
+
+            Each frontend element contain the following attributes:
+                "id": unique id of the frontend that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "type": the frontend type. The enums are defined in the xsd.
+                "isSoftwareFrontend": if the test environment is using hardware or software
+                    frontend. If using software, a ts input file path needs to be configured.
+                "softwareFeInputPath": used as the source of the software frontend.
+                "connectToCicamId": if the device supports frontend connecting to cicam, the target
+                    cicam id needs to be configured here. Supported in Tuner 1.1 or higher.
+                "frequency": the frequency used to configure tune and scan.
+                "endFrequency": the end frequency of scan. Supported in Tuner 1.1 or higher.
+
+            Each frontend element also contains one and only one type-related "frontendSettings".
+                - The settings type should match the frontend "type" attribute.
+                - For example, when frontend type="DVBT", dvbtFrontendSettings can be configured.
+                - This is optional and skipping the settings would pass a setting with frequency
+                    config only to the hal.
+        -->
+        <frontends>
+            <frontend id="FE_DEFAULT" type="DVBT" isSoftwareFrontend="true"
+                      connectToCicamId="0" frequency="578000000" endFrequency="800000000">
+                <dvbtFrontendSettings bandwidth="8" transmissionMode="128" isHighPriority="1"/>
+            </frontend>
+            <frontend id="FE_DVBS_0" type="DVBS" isSoftwareFrontend="true"
+                      connectToCicamId="0" frequency="578000000" endFrequency="800000000">
+            </frontend>
+        </frontends>
+        <!-- Filter section:
+            This section contains configurations of all the filters that would be used in the tests.
+                - This section is optional and can be skipped to use the default filter settings.
+                - The default settings can be found in the sample_tuner_vts_configurations.xml.
+                - The users can also override the default filter settings using
+                - id="FILTER_AUDIO_DEFAULT" or "FILTER_VIDEO_DEFAULT".
+                - The users can configure 1 or more filter elements in the filters sections.
+
+            Each filter element contain the following attributes:
+                "id": unique id of the filter that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "mainType": the main filter type. The enums are defined in the xsd.
+                "subType": the sub filter type. The enums are defined in the xsd.
+                "bufferSize": the buffer size of the filter in hex.
+                "pid": the pid that would be used to configure the filter.
+                "useFMQ": if the filter uses FMQ.
+
+            Each filter element also contains at most one type-related "filterSettings".
+                - The settings type should match the filter "subType" attribute.
+                - For example, when filter subType is audio or video, the avFilterSettings can be
+                    configured.
+                - This is optional and skipping the settings would pass a setting with tpid config
+                    only to the hal.
+        -->
+        <filters>
+            <filter id="FILTER_AUDIO_DEFAULT" mainType="TS" subType="AUDIO"
+                    bufferSize="16777216" pid="257" useFMQ="false" monitorEventTypes="3">
+                <avFilterSettings isPassthrough="false" isSecureMemory="false">
+                    <audioStreamType>2</audioStreamType>
+                </avFilterSettings>
+            </filter>
+            <filter id="FILTER_VIDEO_DEFAULT" mainType="TS" subType="VIDEO"
+                    bufferSize="16777216" pid="256" useFMQ="false" monitorEventTypes="3">
+                <avFilterSettings isPassthrough="false" isSecureMemory="false">
+                    <videoStreamType>2</videoStreamType>
+                </avFilterSettings>
+            </filter>
+            <filter id="FILTER_TS_RECORD_0" mainType="TS" subType="RECORD"
+                    bufferSize="16777216" pid="257" useFMQ="false">
+                <recordFilterSettings tsIndexMask="1" scIndexType="NONE"/>
+            </filter>
+            <filter id="FILTER_IP_IP_0" mainType="IP" subType="IP" bufferSize="16777216" useFMQ="false" timeDelayInMs="5000">
+                <ipFilterConfig ipCid="1">
+                    <srcIpAddress isIpV4="true" ip="192 168 1 1"/>
+                    <destIpAddress isIpV4="true" ip="192 168 1 1"/>
+                </ipFilterConfig>
+            </filter>
+        </filters>
+        <!-- Dvr section:
+            This section contains configurations of all the dvrs that would be used in the tests.
+                - This section is optional and can be skipped if DVR is not supported.
+                - The users can configure 1 or more dvr elements in the dvrs sections.
+
+            Each dvr element contain the following attributes:
+                "id": unique id of the dvr that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "type": the dvr type.
+                "bufferSize": the dvr buffer size.
+                "statusMask": register callbacks of specific status.
+                "lowThreshold": the dvr status low threshold.
+                "highThreshold": the dvr status high threshold.
+                "dataFormat": the dvr data format.
+                "packetSize": the dvr packet size.
+                "inputFilePath": the dvr playback input file path. Only required in playback dvr.
+        -->
+        <dvrs>
+            <dvr id="DVR_PLAYBACK_0" type="PLAYBACK" bufferSize="4194304"
+                 statusMask="15" lowThreshold="4096" highThreshold="32767"
+                 dataFormat="TS" packetSize="188" inputFilePath="/data/local/tmp/segment000000.ts"/>
+            <dvr id="DVR_RECORD_0" type="RECORD" bufferSize="4194304"
+                 statusMask="15" lowThreshold="4096" highThreshold="32767"
+                 dataFormat="TS" packetSize="188"/>
+            <dvr id="DVR_PLAYBACK_1" type="PLAYBACK" bufferSize="4194304"
+                 statusMask="15" lowThreshold="4096" highThreshold="32767"
+                 dataFormat="ES" packetSize="188" inputFilePath="/data/local/tmp/test.es"/>
+        </dvrs>
+    </hardwareConfiguration>
+
+    <!-- Data flow configuration section connects each data flow under test to the ids of the
+        hardwares that would be used during the tests. -->
+    <dataFlowConfiguration>
+        <clearLiveBroadcast frontendConnection="FE_DEFAULT"
+                            audioFilterConnection="FILTER_AUDIO_DEFAULT"
+                            videoFilterConnection="FILTER_VIDEO_DEFAULT"
+                            ipFilterConnection="FILTER_IP_IP_0"
+                            dvrSoftwareFeConnection="DVR_PLAYBACK_1"/>
+        <scan frontendConnection="FE_DEFAULT"/>
+        <dvrPlayback dvrConnection="DVR_PLAYBACK_1"
+                     audioFilterConnection="FILTER_AUDIO_DEFAULT"
+                     videoFilterConnection="FILTER_VIDEO_DEFAULT"/>
+        <dvrRecord hasFrontendConnection="true"
+                   frontendConnection="FE_DEFAULT"
+                   recordFilterConnection="FILTER_TS_RECORD_0"
+                   dvrRecordConnection="DVR_RECORD_0"
+                   dvrSoftwareFeConnection="DVR_PLAYBACK_1"/>
+    </dataFlowConfiguration>
+</TunerConfiguration>
diff --git a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
index 6a04b7e..54cedfc 100644
--- a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
+++ b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
@@ -191,7 +191,7 @@
             <xs:enumeration value="IP"/>
             <xs:enumeration value="NTP"/>
             <xs:enumeration value="IP_PAYLOAD"/>
-            <xs:enumeration value="PAYLOAD_THROUGH"/>            
+            <xs:enumeration value="PAYLOAD_THROUGH"/>
         </xs:restriction>
     </xs:simpleType>
 
@@ -220,6 +220,7 @@
             <xs:element name="videoStreamType" type="xs:unsignedByte"/>
         </xs:choice>
         <xs:attribute name="isPassthrough" type="xs:boolean" use="required"/>
+        <xs:attribute name="isSecureMemory" type="xs:boolean" use="required"/>
     </xs:complexType>
     <xs:complexType name="sectionFilterSettings">
         <xs:attribute name="isCheckCrc" type="xs:boolean" use="required"/>
@@ -242,6 +243,10 @@
                     "bufferSize": the buffer size of the filter in hex.
                     "pid": the pid that would be used to configure the filter.
                     "useFMQ": if the filter uses FMQ.
+                    "timeDelayInMs": the filter's time delay hint. 0 by default.  Must not be
+                        longer than 30 seconds.
+                    "dataDelayInBytes": the filter's data delay hint. 0 by default. Configured data
+                        size must be received within 30 seconds.
 
                 Each filter element also contains at most one type-related "filterSettings".
                     - The settings type should match the filter "subType" attribute.
@@ -273,6 +278,8 @@
         <xs:attribute name="pid" type="xs:nonNegativeInteger" use="optional"/>
         <xs:attribute name="useFMQ" type="xs:boolean" use="required"/>
         <xs:attribute name="monitorEventTypes" type="monitoEvents" use="optional"/>
+        <xs:attribute name="timeDelayInMs" type="xs:nonNegativeInteger" use="optional"/>
+        <xs:attribute name="dataDelayInBytes" type="xs:nonNegativeInteger" use="optional"/>
     </xs:complexType>
 
     <!-- DVR SESSION -->
diff --git a/uwb/OWNERS b/uwb/OWNERS
new file mode 100644
index 0000000..c4ad416
--- /dev/null
+++ b/uwb/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 1042770
+include platform/packages/modules/Uwb:/OWNERS
diff --git a/uwb/aidl/Android.bp b/uwb/aidl/Android.bp
new file mode 100755
index 0000000..99fd094
--- /dev/null
+++ b/uwb/aidl/Android.bp
@@ -0,0 +1,64 @@
+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"],
+}
+
+// TODO(b/195992901): Add VTS tests.
+// TODO(b/195992658): Add cuttlefish implementation.
+aidl_interface {
+    name: "android.hardware.uwb",
+    vendor_available: true,
+    srcs: ["android/hardware/uwb/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+            enabled: false,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.uwb",
+            ],
+            min_sdk_version: "current",
+        },
+        rust: {
+            enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.uwb",
+            ],
+            min_sdk_version: "current",
+        },
+    },
+}
+
+aidl_interface {
+    name: "android.hardware.uwb.fira_android",
+    vendor_available: true,
+    srcs: ["android/hardware/uwb/fira_android/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+            enabled: true,
+            apex_available: [
+                "com.android.uwb",
+            ],
+        },
+        ndk: {
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.uwb",
+            ],
+            min_sdk_version: "current",
+        },
+    },
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbAndroidCapabilities.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbAndroidCapabilities.aidl
new file mode 100644
index 0000000..7e3be56
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbAndroidCapabilities.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb.fira_android;
+@Backing(type="long") @VintfStability
+enum UwbAndroidCapabilities {
+  POWER_STATS_QUERY = 1,
+  ANTENNAE_INTERLEAVING = 2,
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl
new file mode 100644
index 0000000..cd2e122
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb.fira_android;
+@Backing(type="byte") @VintfStability
+enum UwbVendorGidAndroidOids {
+  ANDROID_GET_POWER_STATS = 0,
+  ANDROID_SET_COUNTRY_CODE = 1,
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGids.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGids.aidl
new file mode 100644
index 0000000..b0d88e0
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGids.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb.fira_android;
+@Backing(type="byte") @VintfStability
+enum UwbVendorGids {
+  ANDROID = 14,
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl
new file mode 100644
index 0000000..30a0a1b
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb.fira_android;
+@Backing(type="int") @VintfStability
+enum UwbVendorSessionInitSessionType {
+  CCC = 160,
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.aidl
new file mode 100644
index 0000000..f449c60
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb.fira_android;
+@Backing(type="int") @VintfStability
+enum UwbVendorSessionSetAppConfigCmdParams {
+  CCC_RANGING_PROTOCOL_VER = 163,
+  CCC_UWB_CONFIG_ID = 164,
+  CCC_PULSESHAPE_COMBO = 165,
+  CCC_URSK_TTL = 166,
+  NB_OF_RANGE_MEASUREMENTS = 227,
+  NB_OF_AZIMUTH_MEASUREMENTS = 228,
+  NB_OF_ELEVATION_MEASUREMENTS = 229,
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwb.aidl b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwb.aidl
new file mode 100644
index 0000000..9553ffc
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwb.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Copyright 2021 NXP.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb;
+@VintfStability
+interface IUwb {
+  List<String> getChips();
+  android.hardware.uwb.IUwbChip getChip(String name);
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwbChip.aidl b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwbChip.aidl
new file mode 100644
index 0000000..c7708f1
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwbChip.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Copyright 2021 NXP.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb;
+@VintfStability
+interface IUwbChip {
+  String getName();
+  void open(in android.hardware.uwb.IUwbClientCallback clientCallback);
+  void close();
+  void coreInit();
+  void sessionInit(int sessionId);
+  int getSupportedAndroidUciVersion();
+  long getSupportedAndroidCapabilities();
+  int sendUciMessage(in byte[] data);
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwbClientCallback.aidl b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwbClientCallback.aidl
new file mode 100644
index 0000000..aac8e96
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwbClientCallback.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Copyright 2021 NXP.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb;
+@VintfStability
+interface IUwbClientCallback {
+  oneway void onUciMessage(in byte[] data);
+  oneway void onHalEvent(in android.hardware.uwb.UwbEvent event, in android.hardware.uwb.UwbStatus status);
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/UwbEvent.aidl b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/UwbEvent.aidl
new file mode 100644
index 0000000..6b30d8c
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/UwbEvent.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Copyright 2021 NXP.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb;
+@Backing(type="int") @VintfStability
+enum UwbEvent {
+  OPEN_CPLT = 0,
+  CLOSE_CPLT = 1,
+  POST_INIT_CPLT = 2,
+  ERROR = 3,
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/UwbStatus.aidl b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/UwbStatus.aidl
new file mode 100644
index 0000000..88d766a
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/UwbStatus.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Copyright 2021 NXP.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb;
+@Backing(type="int") @VintfStability
+enum UwbStatus {
+  OK = 0,
+  FAILED = 1,
+  ERR_TRANSPORT = 2,
+  ERR_CMD_TIMEOUT = 3,
+  REFUSED = 4,
+}
diff --git a/uwb/aidl/android/hardware/uwb/IUwb.aidl b/uwb/aidl/android/hardware/uwb/IUwb.aidl
new file mode 100755
index 0000000..fda726c
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/IUwb.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Copyright 2021 NXP.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.uwb;
+
+import android.hardware.uwb.IUwbChip;
+
+/**
+ * HAL Interface for UWB (Ultrawideband) subsystem.
+ * https://en.wikipedia.org/wiki/Ultra-wideband.
+ */
+@VintfStability
+interface IUwb {
+    /**
+     * Returns list of IUwbChip instance names representing each UWB chip on the device.
+     */
+    List<String> getChips();
+
+    /**
+     * Returns IUwbChip instance corresponding to the name.
+     *
+     * @param Unique identifier of the chip.
+     */
+    IUwbChip getChip(String name);
+}
diff --git a/uwb/aidl/android/hardware/uwb/IUwbChip.aidl b/uwb/aidl/android/hardware/uwb/IUwbChip.aidl
new file mode 100644
index 0000000..f2bb0f1
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/IUwbChip.aidl
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Copyright 2021 NXP.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.uwb;
+
+import android.hardware.uwb.IUwbClientCallback;
+import android.hardware.uwb.UwbStatus;
+
+/**
+ * Controls a UWB chip on the device. On some devices, there could be multiple UWB chips.
+ */
+@VintfStability
+interface IUwbChip {
+    /**
+     * Get unique idenitifer for the chip.
+     */
+    String getName();
+
+    /**
+     * Performs the UWB HAL initialization and power on UWB Subsystem. If open completes
+     * successfully, then UWB Subsystem is ready to accept UCI message through write() API
+     *
+     * @param clientCallback Client callback instance.
+     */
+    void open(in IUwbClientCallback clientCallback);
+
+    /**
+     * Close the UWB Subsystem. Should free all resources.
+     */
+    void close();
+
+    /**
+     * Perform UWB Subsystem initialization by applying all vendor configuration.
+     */
+    void coreInit();
+
+    /**
+     * Perform any necessary UWB session initializations.
+     * This must be invoked by the framework at the beginging of every new ranging session.
+     *
+     * @param sessionId Session identifier as defined in the UCI specification.
+     */
+    void sessionInit(int sessionId);
+
+    /**
+     * Supported version of vendor UCI specification.
+     *
+     * @return Returns the version of the "android.hardware.uwb.fira_android" types-only
+     * package included in the HAL implementation. This vendor params/commands package will be
+     * updated on a different cadence to the main UWB HAL interface package.
+     */
+    int getSupportedAndroidUciVersion();
+
+    /**
+     * Mechanism to allow HAL implementation to optionally expose features that are defined
+     * in the "android.hardware.uwb.fira_android" types-only package.
+     *
+     * @return Returns the bitmask of capabilities
+     * (android.hardware.uwb.fira_android.UwbAndroidCapabilities) that is supported by the
+     * HAL implementation.
+     */
+    long getSupportedAndroidCapabilities();
+
+    /**
+     * Write the UCI message to the UWB Subsystem.
+     * The UCI message format is as per UCI  protocol and it is
+     * defined in "FiRa Consortium - UCI Generic Specification_v1.0" specification at FiRa
+     * consortium.
+     * WIP doc link: https://groups.firaconsortium.org/wg/Technical/document/folder/127.
+     * TODO(b/196004116): Link to the published specification.
+     *
+     * This method may queue writes and return immediately, or it may block until data is written.
+     * Implementation must guarantee that writes are executed in order.
+     *
+     * @param data UCI packet to write.
+     * @return number of bytes written to the UWB Subsystem
+     */
+    int sendUciMessage(in byte[] data);
+}
diff --git a/uwb/aidl/android/hardware/uwb/IUwbClientCallback.aidl b/uwb/aidl/android/hardware/uwb/IUwbClientCallback.aidl
new file mode 100755
index 0000000..75853cd
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/IUwbClientCallback.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Copyright 2021 NXP.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.uwb;
+
+import android.hardware.uwb.UwbEvent;
+import android.hardware.uwb.UwbStatus;
+
+@VintfStability
+oneway interface IUwbClientCallback {
+    /**
+     * The callback passed in from the UWB stack that the HAL
+     * can use to pass incoming data to the stack.  These include UCI
+     * responses and notifications from the UWB subsystem.
+     *
+     * WIP doc link: https://groups.firaconsortium.org/wg/Technical/document/folder/127.
+     * TODO(b/196004116): Link to the published specification.
+     *
+     * @param data UCI packet sent.
+     */
+    void onUciMessage(in byte[] data);
+
+    /**
+     * The callback passed in from the UWB stack that the HAL
+     * can use to pass events back to the stack.
+     *
+     * @param event Asynchronous event type.
+     * @param status Associated status.
+     */
+    void onHalEvent(in UwbEvent event, in UwbStatus status);
+}
diff --git a/uwb/aidl/android/hardware/uwb/UwbEvent.aidl b/uwb/aidl/android/hardware/uwb/UwbEvent.aidl
new file mode 100755
index 0000000..3457836
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/UwbEvent.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Copyright 2021 NXP.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.uwb;
+
+/**
+ * Asynchronous events sent from the UWB subsystem.
+ */
+@VintfStability
+@Backing(type="int")
+enum UwbEvent {
+    /** Open request processing completed. */
+    OPEN_CPLT = 0,
+    /** Close request processing completed. */
+    CLOSE_CPLT = 1,
+    /** Post initialization processing completed. */
+    POST_INIT_CPLT = 2,
+    /** Fatal error encountered. */
+    ERROR = 3,
+}
diff --git a/uwb/aidl/android/hardware/uwb/UwbStatus.aidl b/uwb/aidl/android/hardware/uwb/UwbStatus.aidl
new file mode 100755
index 0000000..d568c5b
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/UwbStatus.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Copyright 2021 NXP.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.uwb;
+
+@VintfStability
+@Backing(type="int")
+enum UwbStatus {
+    OK = 0,
+    FAILED = 1,
+    ERR_TRANSPORT = 2,
+    ERR_CMD_TIMEOUT = 3,
+    REFUSED = 4,
+}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/README.md b/uwb/aidl/android/hardware/uwb/fira_android/README.md
new file mode 100644
index 0000000..e658d93
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/README.md
@@ -0,0 +1,15 @@
+The `android.hardware.uwb.fira_android` package is used to add any Android specific
+additions to the UCI specification defined by FIRA standards body. These
+additions should be added to the vendor specific portions carved out in the UCI
+specification.
+
+These include:
+ - Android specific GIDs/OIDs for commands/responses/notifications.
+ - Andriod specific params in an existing UCI specified command/response/notification.
+
+All other interactions sent/received over the HAL interface is expected to
+comply with the UCI specification that can be found [here](
+https://groups.firaconsortium.org/wg/Technical/document/folder/127).
+
+TODO([b/196004116](b/196004116)): Link to the published specification.
+
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbAndroidCapabilities.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbAndroidCapabilities.aidl
new file mode 100644
index 0000000..0af99e0
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbAndroidCapabilities.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.uwb.fira_android;
+
+/**
+ * Android specific capabilities should be defined here.
+ *
+ * For any features enabled via the FIRA vendor commands for Android, use this bitmask
+ * to allow devices to expose the features supported by the HAL implementation.
+ *
+ */
+@VintfStability
+@Backing(type="long")
+enum UwbAndroidCapabilities {
+    POWER_STATS_QUERY = 0x1,
+    ANTENNAE_INTERLEAVING = 0x2,
+}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl
new file mode 100644
index 0000000..1dfcd6f
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGidAndroidOids.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.uwb.fira_android;
+
+/**
+ * Android specific vendor command OIDs should be defined here.
+ *
+ */
+@VintfStability
+@Backing(type="byte")
+enum UwbVendorGidAndroidOids {
+    // Used by the command and response to get UWB power related stats.
+    // Supported only if the value returned by getSupportedAndroidCapabilities()
+    // has the bit of UwbAndroidCapabilities.POWER_STATS_QUERY set to 1.
+    ANDROID_GET_POWER_STATS = 0x0,
+    // Used to set the current regulatory country code (determined usinag
+    // SIM or hardcoded by OEM).
+    ANDROID_SET_COUNTRY_CODE = 0x1,
+}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGids.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGids.aidl
new file mode 100644
index 0000000..c7bc6b0
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGids.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.uwb.fira_android;
+
+/**
+ * Android specific vendor command GIDs (Group ID) should be defined here.
+ *
+ * For each vendor GID defined here, also create a corresponding AIDL file enumerating the
+ * OIDs (Opcode Identifier) allowed within that GID.
+ * For ex: VENDOR_GID_XXX = 1110b -> UwbVendorGidXXXOids.aidl
+ */
+@VintfStability
+@Backing(type="byte")
+enum UwbVendorGids {
+    /**
+     * Use values from the Proprietary Group range: 1110b – 1111b defined in Table 36 of
+     * UCI specification.
+     */
+
+    /** All Android specific commands/response/notification should use this GID */
+    ANDROID = 0xE,
+}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl
new file mode 100644
index 0000000..1e2c817
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionInitSessionType.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.uwb.fira_android;
+
+/**
+ * Android specific session type set in UCI command:
+ * GID: 0001b (UWB Session config Group)
+ * OID: 000000b (SESSION_INIT_CMD)
+ *
+ * Note: Refer to Table 13 of the UCI specification for the other
+ * session types.
+ */
+@VintfStability
+@Backing(type="int")
+enum UwbVendorSessionInitSessionType {
+    /** Added in vendor version 0. */
+    CCC = 0xA0,
+}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.aidl
new file mode 100644
index 0000000..f5e02c0
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.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.uwb.fira_android;
+
+/**
+ * Android specific vendor app params set in UCI command:
+ * GID: 0001b (UWB Session config Group)
+ * OID: 000011b (SESSION_SET_APP_CONFIG_CMD)
+ *
+ * Note: Refer to Table 34 of the UCI specification for the other params
+ * expected in this command.
+ */
+@VintfStability
+@Backing(type="int")
+enum UwbVendorSessionSetAppConfigCmdParams {
+    /** CCC params for ranging start */
+
+    /**
+     * Added in vendor version 0.
+     * Range 0xA0 - 0xDF reserved for CCC use.
+     */
+    CCC_RANGING_PROTOCOL_VER = 0xA3,
+    CCC_UWB_CONFIG_ID = 0xA4,
+    CCC_PULSESHAPE_COMBO = 0xA5,
+    CCC_URSK_TTL = 0xA6,
+
+    /**
+     * Range 0xE3 - 0xFF is reserved for proprietary use in the FIRA spec.
+     * In Android, this range is reserved by the Android platform for Android-specific
+     * app config cmd params.
+     * Vendors must not define additional app config cmd params in this range.
+     */
+
+    /**
+     * Added in vendor version 0.
+     * Interleaving ratio if AOA_RESULT_REQ is set to 0xF0.
+     * Supported only if the value returned by getSupportedAndroidCapabilities()
+     * has the bit of UwbAndroidCapabilities.ANTENNAE_INTERLEAVING set to 1.
+     */
+    NB_OF_RANGE_MEASUREMENTS = 0xE3,
+    NB_OF_AZIMUTH_MEASUREMENTS = 0xE4,
+    NB_OF_ELEVATION_MEASUREMENTS = 0xE5,
+}
diff --git a/uwb/aidl/default/Android.bp b/uwb/aidl/default/Android.bp
new file mode 100644
index 0000000..8c2b60e
--- /dev/null
+++ b/uwb/aidl/default/Android.bp
@@ -0,0 +1,35 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+    name: "android.hardware.uwb-service",
+    relative_install_path: "hw",
+    init_rc: ["uwb-service.rc"],
+    vintf_fragments: ["uwb-service.xml"],
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-g",
+    ],
+    shared_libs: [
+        "liblog",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "libbase",
+        "libutils",
+        "android.hardware.uwb-V1-ndk",
+    ],
+    srcs: [
+        "service.cpp",
+        "uwb.cpp",
+        "uwb_chip.cpp",
+    ],
+}
diff --git a/uwb/aidl/default/service.cpp b/uwb/aidl/default/service.cpp
new file mode 100644
index 0000000..007637f
--- /dev/null
+++ b/uwb/aidl/default/service.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <utils/StrongPointer.h>
+
+#include "uwb.h"
+
+using ::aidl::android::hardware::uwb::IUwb;
+using ::android::sp;
+using ::android::base::InitLogging;
+using ::android::base::StderrLogger;
+using ::android::hardware::uwb::impl::Uwb;
+
+int main(int /*argc*/, char* argv[]) {
+    InitLogging(argv, StderrLogger);
+    LOG(INFO) << "UWB HAL starting up";
+
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    std::shared_ptr<IUwb> uwb = ndk::SharedRefBase::make<Uwb>();
+    const std::string instance = std::string() + IUwb::descriptor + "/default";
+    binder_status_t status = AServiceManager_addService(uwb->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reach
+}
diff --git a/uwb/aidl/default/uwb-service.rc b/uwb/aidl/default/uwb-service.rc
new file mode 100644
index 0000000..e2c3825
--- /dev/null
+++ b/uwb/aidl/default/uwb-service.rc
@@ -0,0 +1,3 @@
+service vendor.uwb_hal /vendor/bin/hw/android.hardware.uwb-service
+    class hal
+    user uwb
diff --git a/uwb/aidl/default/uwb-service.xml b/uwb/aidl/default/uwb-service.xml
new file mode 100644
index 0000000..013d9de
--- /dev/null
+++ b/uwb/aidl/default/uwb-service.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.uwb</name>
+        <version>1</version>
+        <interface>
+            <name>IUwb</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/uwb/aidl/default/uwb.cpp b/uwb/aidl/default/uwb.cpp
new file mode 100644
index 0000000..1e2ef4e
--- /dev/null
+++ b/uwb/aidl/default/uwb.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <android-base/logging.h>
+
+#include "uwb.h"
+
+namespace {
+static constexpr char kDefaultChipName[] = "default";
+
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace uwb {
+namespace impl {
+using namespace ::aidl::android::hardware::uwb;
+
+// The default implementation of the HAL assumes 1 chip on the device.
+Uwb::Uwb() : chips_({{kDefaultChipName, ndk::SharedRefBase::make<UwbChip>(kDefaultChipName)}}) {}
+
+Uwb::~Uwb() {}
+
+::ndk::ScopedAStatus Uwb::getChips(std::vector<std::string>* names) {
+    for (const auto& chip : chips_) {
+        names->push_back(chip.first);
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Uwb::getChip(const std::string& name, std::shared_ptr<IUwbChip>* chip) {
+    const auto chip_found = chips_.find(name);
+    if (chip_found == chips_.end()) {
+        LOG(ERROR) << "Unknown chip name" << name;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    *chip = chip_found->second;
+    return ndk::ScopedAStatus::ok();
+}
+}  // namespace impl
+}  // namespace uwb
+}  // namespace hardware
+}  // namespace android
diff --git a/uwb/aidl/default/uwb.h b/uwb/aidl/default/uwb.h
new file mode 100644
index 0000000..ec51fd8
--- /dev/null
+++ b/uwb/aidl/default/uwb.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_UWB_UWB
+#define ANDROID_HARDWARE_UWB_UWB
+
+#include <map>
+#include <vector>
+
+#include <aidl/android/hardware/uwb/BnUwb.h>
+#include <aidl/android/hardware/uwb/IUwbChip.h>
+
+#include "uwb_chip.h"
+
+namespace android {
+namespace hardware {
+namespace uwb {
+namespace impl {
+using namespace ::aidl::android::hardware::uwb;
+// Default implementation mean't to be used on simulator targets.
+class Uwb : public BnUwb {
+  public:
+    Uwb();
+    virtual ~Uwb();
+
+    ::ndk::ScopedAStatus getChips(std::vector<std::string>* names) override;
+    ::ndk::ScopedAStatus getChip(const std::string& name, std::shared_ptr<IUwbChip>* chip) override;
+
+  private:
+    std::map<std::string, std::shared_ptr<UwbChip>> chips_;
+};
+}  // namespace impl
+}  // namespace uwb
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_UWB_UWB
\ No newline at end of file
diff --git a/uwb/aidl/default/uwb_chip.cpp b/uwb/aidl/default/uwb_chip.cpp
new file mode 100644
index 0000000..a5a3f4a
--- /dev/null
+++ b/uwb/aidl/default/uwb_chip.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#include "uwb.h"
+
+namespace {
+constexpr static int32_t kAndroidUciVersion = 1;
+constexpr static int64_t kAndroidCapabilities = 0;
+}
+
+namespace android {
+namespace hardware {
+namespace uwb {
+namespace impl {
+using namespace ::aidl::android::hardware::uwb;
+
+UwbChip::UwbChip(const std::string& name) : name_(name), mClientCallback(nullptr) {}
+UwbChip::~UwbChip() {}
+
+::ndk::ScopedAStatus UwbChip::getName(std::string* name) {
+    *name = name_;
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus UwbChip::open(const std::shared_ptr<IUwbClientCallback>& clientCallback) {
+    mClientCallback = clientCallback;
+    mClientCallback->onHalEvent(UwbEvent::OPEN_CPLT, UwbStatus::OK);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus UwbChip::close() {
+    mClientCallback->onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK);
+    mClientCallback = nullptr;
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus UwbChip::coreInit() {
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus UwbChip::sessionInit(int /* sessionId */) {
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus UwbChip::getSupportedAndroidUciVersion(int32_t* version) {
+    *version = kAndroidUciVersion;
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus UwbChip::getSupportedAndroidCapabilities(int64_t* capabilities) {
+    *capabilities = kAndroidCapabilities;
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus UwbChip::sendUciMessage(const std::vector<uint8_t>& /* data */,
+                                             int32_t* /* bytes_written */) {
+    // TODO(b/195992658): Need emulator support for UCI stack.
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+}  // namespace impl
+}  // namespace uwb
+}  // namespace hardware
+}  // namespace android
diff --git a/uwb/aidl/default/uwb_chip.h b/uwb/aidl/default/uwb_chip.h
new file mode 100644
index 0000000..46cecd4
--- /dev/null
+++ b/uwb/aidl/default/uwb_chip.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_UWB_UWBCHIP
+#define ANDROID_HARDWARE_UWB_UWBCHIP
+
+#include <vector>
+
+#include <aidl/android/hardware/uwb/BnUwbChip.h>
+#include <aidl/android/hardware/uwb/IUwbClientCallback.h>
+
+namespace android {
+namespace hardware {
+namespace uwb {
+namespace impl {
+using namespace ::aidl::android::hardware::uwb;
+// Default implementation mean't to be used on simulator targets.
+class UwbChip : public BnUwbChip {
+  public:
+    UwbChip(const std::string& name);
+    virtual ~UwbChip();
+
+    ::ndk::ScopedAStatus getName(std::string* name) override;
+    ::ndk::ScopedAStatus open(const std::shared_ptr<IUwbClientCallback>& clientCallback) override;
+    ::ndk::ScopedAStatus close() override;
+    ::ndk::ScopedAStatus coreInit() override;
+    ::ndk::ScopedAStatus sessionInit(int sesionId) override;
+    ::ndk::ScopedAStatus getSupportedAndroidUciVersion(int32_t* version) override;
+    ::ndk::ScopedAStatus getSupportedAndroidCapabilities(int64_t* capabilities) override;
+    ::ndk::ScopedAStatus sendUciMessage(const std::vector<uint8_t>& data,
+                                        int32_t* bytes_written) override;
+
+  private:
+    std::string name_;
+    std::shared_ptr<IUwbClientCallback> mClientCallback;
+};
+}  // namespace impl
+}  // namespace uwb
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_UWB_UWBCHIP
diff --git a/uwb/aidl/vts/Android.bp b/uwb/aidl/vts/Android.bp
new file mode 100644
index 0000000..4d9f653
--- /dev/null
+++ b/uwb/aidl/vts/Android.bp
@@ -0,0 +1,28 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalUwbTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalUwbTargetTest.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.uwb-V1-ndk",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/uwb/aidl/vts/VtsHalUwbTargetTest.cpp b/uwb/aidl/vts/VtsHalUwbTargetTest.cpp
new file mode 100644
index 0000000..1da4432
--- /dev/null
+++ b/uwb/aidl/vts/VtsHalUwbTargetTest.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the std::shared_ptrecific language governing permissions and
+ * limitations under the License.
+ */
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/uwb/BnUwbClientCallback.h>
+#include <aidl/android/hardware/uwb/IUwb.h>
+#include <aidl/android/hardware/uwb/IUwbChip.h>
+#include <aidl/android/hardware/uwb/IUwbClientCallback.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include <future>
+
+using aidl::android::hardware::uwb::BnUwbClientCallback;
+using aidl::android::hardware::uwb::IUwb;
+using aidl::android::hardware::uwb::IUwbChip;
+using aidl::android::hardware::uwb::IUwbClientCallback;
+using aidl::android::hardware::uwb::UwbEvent;
+using aidl::android::hardware::uwb::UwbStatus;
+using android::ProcessState;
+using android::String16;
+using ndk::ScopedAStatus;
+using ndk::SpAIBinder;
+
+namespace {
+constexpr static int kCallbackTimeoutMs = 250;
+}  // namespace
+
+class UwbClientCallback : public BnUwbClientCallback {
+  public:
+    UwbClientCallback(const std::function<void(const std::vector<uint8_t>&)>& on_uci_message_cb,
+                      const std::function<void(UwbEvent, UwbStatus)>& on_hal_event_cb)
+        : on_uci_message_cb_(on_uci_message_cb), on_hal_event_cb_(on_hal_event_cb) {}
+
+    ScopedAStatus onUciMessage(const std::vector<uint8_t>& data) override {
+        on_uci_message_cb_(data);
+        return ScopedAStatus::ok();
+    }
+
+    ScopedAStatus onHalEvent(UwbEvent uwb_event, UwbStatus uwb_status) override {
+        on_hal_event_cb_(uwb_event, uwb_status);
+        return ScopedAStatus::ok();
+    }
+
+  private:
+    std::function<void(const std::vector<uint8_t>&)> on_uci_message_cb_;
+    std::function<void(UwbEvent, UwbStatus)> on_hal_event_cb_;
+};
+
+class UwbAidl : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        iuwb_ = IUwb::fromBinder(SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+        ASSERT_NE(iuwb_, nullptr);
+    }
+    std::shared_ptr<IUwb> iuwb_;
+
+    // TODO (b/197638976): We pick the first chip here. Need to fix this
+    // for supporting multiple chips in the future.
+    std::string getAnyChipName() {
+        std::vector<std::string> chip_names;
+        ScopedAStatus status = iuwb_->getChips(&chip_names);
+        EXPECT_TRUE(status.isOk());
+        EXPECT_FALSE(chip_names.empty());
+        return chip_names[0];
+    }
+
+    // TODO (b/197638976): We pick the first chip here. Need to fix this
+    // for supporting multiple chips in the future.
+    std::shared_ptr<IUwbChip> getAnyChip() {
+        std::shared_ptr<IUwbChip> iuwb_chip;
+        ScopedAStatus status = iuwb_->getChip(getAnyChipName(), &iuwb_chip);
+        EXPECT_TRUE(status.isOk());
+        EXPECT_NE(iuwb_chip, nullptr);
+        return iuwb_chip;
+    }
+
+    std::shared_ptr<IUwbChip> getAnyChipAndOpen() {
+        std::promise<void> open_cb_promise;
+        std::future<void> open_cb_future{open_cb_promise.get_future()};
+        std::shared_ptr<UwbClientCallback> callback = ndk::SharedRefBase::make<UwbClientCallback>(
+                [](auto /* data */) {},
+                [&open_cb_promise](auto event, auto /* status */) {
+                    if (event == UwbEvent::OPEN_CPLT) {
+                        open_cb_promise.set_value();
+                    }
+                });
+        std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+        const auto iuwb_chip = getAnyChip();
+        EXPECT_TRUE(iuwb_chip->open(callback).isOk());
+        EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+        return iuwb_chip;
+    }
+};
+
+TEST_P(UwbAidl, GetChips) {
+    std::vector<std::string> chip_names;
+    ScopedAStatus status = iuwb_->getChips(&chip_names);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_FALSE(chip_names.empty());
+}
+
+TEST_P(UwbAidl, GetChip) {
+    std::shared_ptr<IUwbChip> iuwb_chip;
+    ScopedAStatus status = iuwb_->getChip(getAnyChipName(), &iuwb_chip);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_NE(iuwb_chip, nullptr);
+}
+
+TEST_P(UwbAidl, ChipOpen) {
+    std::promise<void> open_cb_promise;
+    std::future<void> open_cb_future{open_cb_promise.get_future()};
+    std::shared_ptr<UwbClientCallback> callback = ndk::SharedRefBase::make<UwbClientCallback>(
+            [](auto /* data */) {},
+            [&open_cb_promise](auto event, auto /* status */) {
+                if (event == UwbEvent::OPEN_CPLT) {
+                    open_cb_promise.set_value();
+                }
+            });
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    const auto iuwb_chip = getAnyChip();
+    EXPECT_TRUE(iuwb_chip->open(callback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+TEST_P(UwbAidl, ChipClose) {
+    std::promise<void> open_cb_promise;
+    std::future<void> open_cb_future{open_cb_promise.get_future()};
+    std::promise<void> close_cb_promise;
+    std::future<void> close_cb_future{close_cb_promise.get_future()};
+    std::shared_ptr<UwbClientCallback> callback = ndk::SharedRefBase::make<UwbClientCallback>(
+            [](auto /* data */) {},
+            [&open_cb_promise, &close_cb_promise](auto event, auto /* status */) {
+                if (event == UwbEvent::OPEN_CPLT) {
+                    open_cb_promise.set_value();
+                }
+                if (event == UwbEvent::CLOSE_CPLT) {
+                    close_cb_promise.set_value();
+                }
+            });
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    const auto iuwb_chip = getAnyChip();
+    EXPECT_TRUE(iuwb_chip->open(callback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+    EXPECT_TRUE(iuwb_chip->close().isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+TEST_P(UwbAidl, ChipCoreInit) {
+    const auto iuwb_chip = getAnyChipAndOpen();
+    EXPECT_TRUE(iuwb_chip->coreInit().isOk());
+}
+
+TEST_P(UwbAidl, ChipSessionInit) {
+    const auto iuwb_chip = getAnyChipAndOpen();
+    EXPECT_TRUE(iuwb_chip->sessionInit(0).isOk());
+}
+
+TEST_P(UwbAidl, ChipGetSupportedAndroidUciVersion) {
+    const auto iuwb_chip = getAnyChipAndOpen();
+    EXPECT_TRUE(iuwb_chip->coreInit().isOk());
+
+    int32_t version;
+    EXPECT_TRUE(iuwb_chip->getSupportedAndroidUciVersion(&version).isOk());
+    EXPECT_GT(version, 0);
+}
+
+TEST_P(UwbAidl, ChipGetSupportedAndroidCapabilities) {
+    const auto iuwb_chip = getAnyChipAndOpen();
+    EXPECT_TRUE(iuwb_chip->coreInit().isOk());
+
+    int64_t capabilities;
+    EXPECT_TRUE(iuwb_chip->getSupportedAndroidCapabilities(&capabilities).isOk());
+}
+
+TEST_P(UwbAidl, ChipGetName) {
+    std::string chip_name = getAnyChipName();
+    std::shared_ptr<IUwbChip> iuwb_chip;
+    ScopedAStatus status = iuwb_->getChip(chip_name, &iuwb_chip);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_NE(iuwb_chip, nullptr);
+
+    std::string retrieved_chip_name;
+    status = iuwb_chip->getName(&retrieved_chip_name);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_EQ(retrieved_chip_name, chip_name);
+}
+
+/**
+TEST_P(UwbAidl, ChipSendUciMessage_GetDeviceInfo) {
+const auto iuwb_chip = getAnyChipAndOpen(callback);
+EXPECT_TRUE(iuwb_chip->coreInit(callback).isOk());
+
+const std::vector<uint8_t>
+EXPECT_TRUE(iuwb_chip->sendUciMessage().isOk());
+} */
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UwbAidl);
+INSTANTIATE_TEST_SUITE_P(Uwb, UwbAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IUwb::descriptor)),
+                         android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 53f8c0e..09cc21b 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -417,6 +417,9 @@
 
             if (isPrimitiveSupported) {
                 EXPECT_EQ(Status::EX_NONE, status.exceptionCode());
+                if (primitive != CompositePrimitive::NOOP) {
+                    ASSERT_GT(duration, 0) << toString(primitive) << " " << duration;
+                }
             } else {
                 EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
             }
diff --git a/vibrator/bench/Android.bp b/vibrator/bench/Android.bp
index e4c9cfb..73e274f 100644
--- a/vibrator/bench/Android.bp
+++ b/vibrator/bench/Android.bp
@@ -29,7 +29,7 @@
         "benchmark.cpp",
     ],
     shared_libs: [
-        "android.hardware.vibrator-V1-cpp",
+        "android.hardware.vibrator-V2-cpp",
         "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
         "android.hardware.vibrator@1.2",
diff --git a/wifi/.clang-format b/wifi/.clang-format
deleted file mode 100644
index 25ed932..0000000
--- a/wifi/.clang-format
+++ /dev/null
@@ -1,2 +0,0 @@
-BasedOnStyle: Google
-IndentWidth: 4
\ No newline at end of file
diff --git a/wifi/1.5/default/wifi_iface_util.cpp b/wifi/1.5/default/wifi_iface_util.cpp
index 7bf830b..0977026 100644
--- a/wifi/1.5/default/wifi_iface_util.cpp
+++ b/wifi/1.5/default/wifi_iface_util.cpp
@@ -56,14 +56,21 @@
 bool WifiIfaceUtil::setMacAddress(const std::string& iface_name,
                                   const std::array<uint8_t, 6>& mac) {
 #ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
-    if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) {
+    legacy_hal::wifi_error legacy_status;
+    uint64_t legacy_feature_set;
+    std::tie(legacy_status, legacy_feature_set) =
+        legacy_hal_.lock()->getSupportedFeatureSet(iface_name);
+
+    if (!(legacy_feature_set & WIFI_FEATURE_DYNAMIC_SET_MAC) &&
+        !iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) {
         LOG(ERROR) << "SetUpState(false) failed.";
         return false;
     }
 #endif
     bool success = iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac);
 #ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
-    if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) {
+    if (!(legacy_feature_set & WIFI_FEATURE_DYNAMIC_SET_MAC) &&
+        !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() !=
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapdCallback.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapdCallback.aidl
index 36d2104..9dd062a 100644
--- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapdCallback.aidl
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapdCallback.aidl
@@ -36,5 +36,5 @@
 interface IHostapdCallback {
   oneway void onApInstanceInfoChanged(in android.hardware.wifi.hostapd.ApInfo apInfo);
   oneway void onConnectedClientsChanged(in android.hardware.wifi.hostapd.ClientInfo clientInfo);
-  oneway void onFailure(in String ifaceName);
+  oneway void onFailure(in String ifaceName, in String instanceName);
 }
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapdCallback.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapdCallback.aidl
index 7b04944..456f46a 100644
--- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapdCallback.aidl
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapdCallback.aidl
@@ -41,7 +41,10 @@
      * Invoked when an asynchronous failure is encountered in one of the access
      * points added via |IHostapd.addAccessPoint|.
      *
-     * @param ifaceName Name of the interface.
+     * @param ifaceName Name of the interface which was added via
+     *                  |IHostapd.addAccessPoint|.
+     * @param instanceName Name of the AP instance which is associated with
+     *                     the interface.
      */
-    oneway void onFailure(in String ifaceName);
+    oneway void onFailure(in String ifaceName, in String instanceName);
 }
diff --git a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
index 41c54b3..dad7085 100644
--- a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
+++ b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
@@ -232,7 +232,7 @@
         const ::aidl::android::hardware::wifi::hostapd::ClientInfo &) override {
         return ndk::ScopedAStatus::ok();
     }
-    ::ndk::ScopedAStatus onFailure(const std::string &) override {
+    ::ndk::ScopedAStatus onFailure(const std::string&, const std::string&) override {
         return ndk::ScopedAStatus::ok();
     }
 };
diff --git a/wifi/netlinkinterceptor/aidl/Android.bp b/wifi/netlinkinterceptor/aidl/Android.bp
new file mode 100644
index 0000000..924edee
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // 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.net.nlinterceptor",
+    vendor_available: true,
+    srcs: ["android/hardware/net/nlinterceptor/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            enabled: false,
+        },
+    },
+}
diff --git a/wifi/netlinkinterceptor/aidl/aidl_api/NetlinkInterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl b/wifi/netlinkinterceptor/aidl/aidl_api/NetlinkInterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl
new file mode 100644
index 0000000..249b343
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/aidl_api/NetlinkInterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.net.nlinterceptor;
+@VintfStability
+interface IInterceptor {
+  int createSocket(in int nlFamily, in int clientNlPid, in String clientName);
+  void closeSocket(in int nlFamily, in int interceptorNlPid);
+  void subscribeGroup(in int nlFamily, in int interceptorNlPid, in int nlGroup);
+  void unsubscribeGroup(in int nlFamily, in int interceptorNlPid, in int nlGroup);
+}
diff --git a/wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl b/wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl
new file mode 100644
index 0000000..3d0f955
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.net.nlinterceptor;
+@VintfStability
+interface IInterceptor {
+  android.hardware.net.nlinterceptor.InterceptedSocket createSocket(in int nlFamily, in int clientNlPid, in String clientName);
+  void closeSocket(in android.hardware.net.nlinterceptor.InterceptedSocket handle);
+  void subscribeGroup(in android.hardware.net.nlinterceptor.InterceptedSocket handle, in int nlGroup);
+  void unsubscribeGroup(in android.hardware.net.nlinterceptor.InterceptedSocket handle, in int nlGroup);
+}
diff --git a/wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/InterceptedSocket.aidl b/wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/InterceptedSocket.aidl
new file mode 100644
index 0000000..b679be5
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/InterceptedSocket.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.net.nlinterceptor;
+@VintfStability
+parcelable InterceptedSocket {
+  int nlFamily;
+  int portId;
+}
diff --git a/wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/IInterceptor.aidl b/wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/IInterceptor.aidl
new file mode 100644
index 0000000..c222a1e
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/IInterceptor.aidl
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.net.nlinterceptor;
+
+import android.hardware.net.nlinterceptor.InterceptedSocket;
+
+/**
+ * Netlink Interceptor
+ *
+ * This HAL provides a way for Android services to route their Netlink traffic to a location other
+ * than the Kernel. One might want to do this for a variety of reasons:
+ * -> Route Netlink traffic to a different host.
+ * -> Route Netlink traffic to a different VM.
+ * -> Convert Netlink commands into proprietary vendor hardware commands.
+ *
+ * Some important notes regarding Netlink Interceptor.
+ * -> All int values are treated as unsigned.
+ * -> Users of Netlink Interceptor must close their sockets with closeSocket manually.
+ * -> PID != process ID. In this case, it is "port ID", a unique number assigned by the kernel to a
+ *    given Netlink socket.
+ * -> Netlink PIDs are only unique per family. This means that for all NETLINK_GENERIC sockets,
+ *    there can only be one socket with PID "1234". HOWEVER, there can ALSO be a Netlink socket
+ *    using NETLINK_ROUTE which has a PID of "1234". Hence, in order to uniquely identify a Netlink
+ *    socket, both the PID and Netlink Family are required.
+ */
+@VintfStability
+interface IInterceptor {
+    /**
+     * Creates a Netlink socket on both the HU and TCU, and a bi-directional gRPC stream to carry
+     * data between them. This must be closed by the caller with closeSocket().
+     *
+     * @param nlFamily - Netlink Family. Support for families other than NETLINK_GENERIC is still
+     * experimental.
+     * @param clientNlPid - Port ID of the caller's Netlink socket.
+     * @param clientName - Human readable name of the caller. Used for debugging.
+     *
+     * @return InterceptedSocket identifying the socket on the HU allocated for the caller.
+     */
+    InterceptedSocket createSocket(in int nlFamily, in int clientNlPid, in String clientName);
+
+    /**
+     * Closes a socket and gRPC stream given the socket's identifier. This must be invoked manually
+     * by the caller of createSocket().
+     *
+     * @param handle - unique identifier for a socket returned by createSocket.
+     */
+    void closeSocket(in InterceptedSocket handle);
+
+    /**
+     * Subscribes a socket on the TCU to a Netlink multicast group.
+     *
+     * @param handle - unique identifier for a socket returned by createSocket.
+     * @param nlGroup - A single Netlink multicast group that the caller wants to subscribe to.
+     */
+    void subscribeGroup(in InterceptedSocket handle, in int nlGroup);
+
+    /**
+     * Unsubscribes a socket on the TCU from a Netlink multicast group.
+     *
+     * @param handle - unique identifier for a socket returned by createSocket.
+     * @param nlGroup - A single Netlink multicast group that the caller wants to unsubscribe from.
+     */
+    void unsubscribeGroup(in InterceptedSocket handle, in int nlGroup);
+}
diff --git a/wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/InterceptedSocket.aidl b/wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/InterceptedSocket.aidl
new file mode 100644
index 0000000..d74a556
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/InterceptedSocket.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.net.nlinterceptor;
+
+/**
+ * Unique identifier for a Netlink socket.
+ */
+@VintfStability
+parcelable InterceptedSocket {
+    /**
+     * Netlink family of the identified socket
+     */
+    int nlFamily;
+
+    /**
+     * Netlink port ID of the identified socket.
+     */
+    int portId;
+}
diff --git a/wifi/netlinkinterceptor/aidl/default/Android.bp b/wifi/netlinkinterceptor/aidl/default/Android.bp
new file mode 100644
index 0000000..5227e51
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/Android.bp
@@ -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 {
+    // 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.net.nlinterceptor-service.default",
+    init_rc: ["nlinterceptor-default.rc"],
+    vintf_fragments: ["nlinterceptor-default.xml"],
+    vendor: true,
+    relative_install_path: "hw",
+    defaults: ["nlinterceptor@defaults"],
+    shared_libs: [
+        "android.hardware.net.nlinterceptor-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "libnlinterceptor",
+        "libnl++",
+    ],
+    srcs: [
+        "InterceptorRelay.cpp",
+        "NetlinkInterceptor.cpp",
+        "service.cpp",
+        "util.cpp",
+    ],
+}
diff --git a/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.cpp b/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.cpp
new file mode 100644
index 0000000..ded9122
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "InterceptorRelay.h"
+
+#include <android-base/logging.h>
+#include <libnl++/printer.h>
+#include <poll.h>
+
+#include <chrono>
+
+#include "util.h"
+
+namespace android::nlinterceptor {
+using namespace std::chrono_literals;
+
+static constexpr std::chrono::milliseconds kPollTimeout = 300ms;
+static constexpr bool kSuperVerbose = true;
+
+InterceptorRelay::InterceptorRelay(uint32_t nlFamily, uint32_t clientNlPid,
+                                   const std::string& clientName)
+    : mClientName(clientName),
+      mNlSocket(std::make_optional<nl::Socket>(nlFamily, 0, 0)),
+      mClientNlPid(clientNlPid) {}
+
+InterceptorRelay::~InterceptorRelay() {
+    mRunning = false;
+    if (mRelayThread.joinable()) mRelayThread.join();
+}
+
+uint32_t InterceptorRelay::getPid() {
+    auto pidMaybe = mNlSocket->getPid();
+    CHECK(pidMaybe.has_value()) << "Failed to get pid of nl::Socket!";
+    return *pidMaybe;
+}
+
+void InterceptorRelay::relayMessages() {
+    pollfd fds[] = {
+        mNlSocket->preparePoll(POLLIN),
+    };
+    while (mRunning) {
+        if (poll(fds, countof(fds), kPollTimeout.count()) < 0) {
+            PLOG(FATAL) << "poll failed";
+            return;
+        }
+        const auto nlsockEvents = fds[0].revents;
+
+        if (isSocketBad(nlsockEvents)) {
+            LOG(ERROR) << "Netlink socket is bad";
+            mRunning = false;
+            return;
+        }
+        if (!isSocketReadable(nlsockEvents)) continue;
+
+        const auto [msgMaybe, sa] = mNlSocket->receiveFrom();
+        if (!msgMaybe.has_value()) {
+            LOG(ERROR) << "Failed to receive Netlink data!";
+            mRunning = false;
+            return;
+        }
+        const auto msg = *msgMaybe;
+        if (!msg.firstOk()) {
+            LOG(ERROR) << "Netlink packet is malformed!";
+            // Test messages might be empty, this isn't fatal.
+            continue;
+        }
+        if constexpr (kSuperVerbose) {
+            LOG(VERBOSE) << "[" << mClientName
+                         << "] nlMsg: " << nl::toString(msg, NETLINK_GENERIC);
+        }
+
+        uint32_t destinationPid = 0;
+        if (sa.nl_pid == 0) {
+            destinationPid = mClientNlPid;
+        }
+
+        if (!mNlSocket->send(msg, destinationPid)) {
+            LOG(ERROR) << "Failed to send Netlink message!";
+            mRunning = false;
+            return;
+        }
+    }
+    LOG(VERBOSE) << "[" << mClientName << "] Exiting relay thread!";
+}
+
+bool InterceptorRelay::start() {
+    if (mRunning) {
+        LOG(ERROR)
+            << "Can't relay messages: InterceptorRelay is already running!";
+        return false;
+    }
+    if (mRelayThread.joinable()) {
+        LOG(ERROR) << "relay thread is already running!";
+        return false;
+    }
+    if (!mNlSocket.has_value()) {
+        LOG(ERROR) << "Netlink socket not initialized!";
+        return false;
+    }
+
+    mRunning = true;
+    mRelayThread = std::thread(&InterceptorRelay::relayMessages, this);
+
+    LOG(VERBOSE) << "Relay threads initialized";
+    return true;
+}
+
+bool InterceptorRelay::subscribeGroup(uint32_t nlGroup) {
+    return mNlSocket->addMembership(nlGroup);
+}
+
+bool InterceptorRelay::unsubscribeGroup(uint32_t nlGroup) {
+    return mNlSocket->dropMembership(nlGroup);
+}
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.h b/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.h
new file mode 100644
index 0000000..0178c90
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <libnl++/Socket.h>
+
+#include <mutex>
+#include <thread>
+
+namespace android::nlinterceptor {
+
+class InterceptorRelay {
+   public:
+    /**
+     * Wrapper around the netlink socket and thread which relays messages.
+     *
+     * \param nlFamily - netlink family to use for the netlink socket.
+     * \param clientNlPid - pid of the client netlink socket.
+     * \param clientName - name of the client to be used for debugging.
+     */
+    InterceptorRelay(uint32_t nlFamily, uint32_t clientNlPid,
+                     const std::string& clientName);
+
+    /**
+     * Stops the relay thread if running and destroys itself.
+     */
+    ~InterceptorRelay();
+
+    /**
+     * Returns the PID of the internal Netlink socket.
+     *
+     * \return value of PID,
+     */
+    uint32_t getPid();
+
+    /**
+     * Spawns relay thread.
+     */
+    bool start();
+
+    /**
+     * Subscribes the internal socket to a single Netlink multicast group.
+     *
+     * \param nlGroup - Netlink group to subscribe to.
+     * \returns - true for success, false for failure.
+     */
+    bool subscribeGroup(uint32_t nlGroup);
+
+    /**
+     * Unsubscribes the internal socket from a single Netlink multicast group.
+     *
+     * \param nlGroup - Netlink group to unsubscribe from.
+     * \returns - true for success, false for failure.
+     */
+    bool unsubscribeGroup(uint32_t nlGroup);
+
+   private:
+    std::string mClientName;  ///< Name of client (Wificond, for example).
+    std::optional<nl::Socket> mNlSocket;
+    const uint32_t mClientNlPid = 0;  ///< pid of client NL socket.
+
+    /**
+     * If set to true, the relay thread should be running. Setting this to false
+     * stops the relay thread.
+     */
+    std::atomic_bool mRunning = false;
+
+    /**
+     * Reads incoming Netlink messages destined for mNlSocket. If from the
+     * kernel, the message is relayed to the client specified in the
+     * constructor. Otherwise, the message is relayed to the kernel. This will
+     * run as long as mRunning is set to true.
+     */
+    void relayMessages();
+
+    std::thread mRelayThread;
+};
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.cpp b/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.cpp
new file mode 100644
index 0000000..908ecf2
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "NetlinkInterceptor.h"
+
+#include <android-base/logging.h>
+#include <libnl++/Socket.h>
+
+namespace android::nlinterceptor {
+
+ndk::ScopedAStatus NetlinkInterceptor::createSocket(
+    int32_t nlFamilyAidl, int32_t clientNlPidAidl,
+    const std::string& clientName, AidlInterceptedSocket* interceptedSocket) {
+    auto nlFamily = static_cast<uint32_t>(nlFamilyAidl);
+    auto clientNlPid = static_cast<uint32_t>(clientNlPidAidl);
+    uint32_t interceptorNlPid = 0;
+
+    std::unique_ptr<InterceptorRelay> interceptor =
+        std::make_unique<InterceptorRelay>(nlFamily, clientNlPid, clientName);
+
+    interceptorNlPid = interceptor->getPid();
+
+    if (interceptorNlPid == 0) {
+        LOG(ERROR) << "Failed to create a Netlink socket for " << clientName
+                   << ", " << nlFamily << ":" << clientNlPid;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    if (mClientMap.find({nlFamily, interceptorNlPid}) != mClientMap.end()) {
+        LOG(ERROR) << "A socket with pid " << interceptorNlPid
+                   << " already exists!";
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    if (!interceptor->start()) {
+        LOG(ERROR) << "Failed to start interceptor thread!";
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    if (!mClientMap
+             .emplace(InterceptedSocket(nlFamily, interceptorNlPid),
+                      std::move(interceptor))
+             .second) {
+        // If this happens, it is very bad.
+        LOG(FATAL) << "Failed to insert interceptor instance with pid "
+                   << interceptorNlPid << " into map!";
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    interceptedSocket->nlFamily = nlFamily;
+    interceptedSocket->portId = interceptorNlPid;
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus NetlinkInterceptor::closeSocket(
+    const AidlInterceptedSocket& interceptedSocket) {
+    InterceptedSocket sock(interceptedSocket);
+
+    auto interceptorIt = mClientMap.find(sock);
+    if (interceptorIt == mClientMap.end()) {
+        LOG(ERROR) << "closeSocket Failed! No such socket " << sock;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+    mClientMap.erase(interceptorIt);
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus NetlinkInterceptor::subscribeGroup(
+    const AidlInterceptedSocket& interceptedSocket, int32_t nlGroupAidl) {
+    InterceptedSocket sock(interceptedSocket);
+    auto nlGroup = static_cast<uint32_t>(nlGroupAidl);
+
+    auto interceptorIt = mClientMap.find(sock);
+    if (interceptorIt == mClientMap.end()) {
+        LOG(ERROR) << "subscribeGroup failed! No such socket " << sock;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    auto& interceptor = interceptorIt->second;
+    if (!interceptor->subscribeGroup(nlGroup)) {
+        LOG(ERROR) << "Failed to subscribe " << sock << " to " << nlGroup;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus NetlinkInterceptor::unsubscribeGroup(
+    const AidlInterceptedSocket& interceptedSocket, int32_t nlGroupAidl) {
+    InterceptedSocket sock(interceptedSocket);
+    auto nlGroup = static_cast<uint32_t>(nlGroupAidl);
+
+    auto interceptorIt = mClientMap.find(sock);
+    if (interceptorIt == mClientMap.end()) {
+        LOG(ERROR) << "unsubscribeGroup failed! No such socket " << sock;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    auto& interceptor = interceptorIt->second;
+    if (!interceptor->unsubscribeGroup(nlGroup)) {
+        LOG(ERROR) << "Failed to unsubscribe " << sock << " from " << nlGroup;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+    return ndk::ScopedAStatus::ok();
+}
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.h b/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.h
new file mode 100644
index 0000000..8345654
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/net/nlinterceptor/BnInterceptor.h>
+#include <libnlinterceptor/libnlinterceptor.h>
+
+#include <map>
+
+#include "InterceptorRelay.h"
+
+namespace android::nlinterceptor {
+
+class NetlinkInterceptor
+    : public ::aidl::android::hardware::net::nlinterceptor::BnInterceptor {
+    using ClientMap =
+        std::map<::android::nlinterceptor::InterceptedSocket,
+                 std::unique_ptr<::android::nlinterceptor::InterceptorRelay>>;
+
+    using AidlInterceptedSocket =
+        ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket;
+
+   public:
+    ndk::ScopedAStatus createSocket(
+        int32_t nlFamily, int32_t clientNlPid, const std::string& clientName,
+        AidlInterceptedSocket* interceptedSocket) override;
+
+    ndk::ScopedAStatus closeSocket(
+        const AidlInterceptedSocket& interceptedSocket) override;
+
+    ndk::ScopedAStatus subscribeGroup(
+        const AidlInterceptedSocket& interceptedSocket,
+        int32_t nlGroup) override;
+
+    ndk::ScopedAStatus unsubscribeGroup(
+        const AidlInterceptedSocket& interceptedSocket,
+        int32_t nlGroup) override;
+
+   private:
+    ClientMap mClientMap;
+};
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/aidl/default/OWNERS b/wifi/netlinkinterceptor/aidl/default/OWNERS
new file mode 100644
index 0000000..b738dac
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/OWNERS
@@ -0,0 +1,2 @@
+chrisweir@google.com
+twasilczyk@google.com
diff --git a/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.rc b/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.rc
new file mode 100644
index 0000000..353cb27
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.rc
@@ -0,0 +1,4 @@
+service nlinterceptor /vendor/bin/hw/android.hardware.net.nlinterceptor-service.default
+    class hal
+    user root
+    group system inet
diff --git a/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.xml b/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.xml
new file mode 100644
index 0000000..d7d257e
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.xml
@@ -0,0 +1,9 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.net.nlinterceptor</name>
+        <interface>
+            <name>IInterceptor</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/wifi/netlinkinterceptor/aidl/default/service.cpp b/wifi/netlinkinterceptor/aidl/default/service.cpp
new file mode 100644
index 0000000..2aec3a5
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/service.cpp
@@ -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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "NetlinkInterceptor.h"
+
+namespace android::nlinterceptor {
+using namespace std::string_literals;
+
+static void service() {
+    base::SetDefaultTag("nlinterceptor");
+    base::SetMinimumLogSeverity(base::VERBOSE);
+    LOG(DEBUG) << "Netlink Interceptor service starting...";
+
+    // TODO(202549296): Sometimes this causes an Address Sanitizer error.
+    auto interceptor = ndk::SharedRefBase::make<NetlinkInterceptor>();
+    const auto instance = NetlinkInterceptor::descriptor + "/default"s;
+    const auto status = AServiceManager_addService(
+        interceptor->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    LOG(FATAL) << "Netlink Interceptor has stopped";
+}
+
+}  // namespace android::nlinterceptor
+
+int main() {
+    ::android::nlinterceptor::service();
+    return 0;
+}
diff --git a/wifi/netlinkinterceptor/aidl/default/util.cpp b/wifi/netlinkinterceptor/aidl/default/util.cpp
new file mode 100644
index 0000000..c734747
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/util.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "util.h"
+
+#include <poll.h>
+
+namespace android::nlinterceptor {
+
+bool isSocketReadable(const short revents) { return 0 != (revents & POLLIN); }
+
+bool isSocketBad(const short revents) {
+    return 0 != (revents & (POLLERR | POLLHUP | POLLNVAL));
+}
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/aidl/default/util.h b/wifi/netlinkinterceptor/aidl/default/util.h
new file mode 100644
index 0000000..9b8ec63
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/util.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+
+#include <functional>
+
+namespace android::nlinterceptor {
+
+/**
+ * Handy-dandy helper to get the size of a statically initialized array.
+ *
+ * \param N the array to get the size of.
+ * \return the size of the array.
+ */
+template <typename T, size_t N>
+size_t countof(T (&)[N]) {
+    return N;
+}
+
+/**
+ * Helper to check if socket is readable (POLLIN is set).
+ *
+ * \param revents pollfd.revents value to check.
+ * \return true if socket is ready to read.
+ */
+bool isSocketReadable(short revents);
+
+/**
+ * Helper to check if socket is bad (POLLERR, POLLHUP or POLLNVAL is set).
+ *
+ * \param revents pollfd.revents value to check.
+ * \return true if socket is bad.
+ */
+bool isSocketBad(short revents);
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/libnlinterceptor/Android.bp b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
new file mode 100644
index 0000000..00cae32
--- /dev/null
+++ b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
@@ -0,0 +1,65 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_defaults {
+    name: "nlinterceptor@defaults",
+    cpp_std: "experimental",
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Wsuggest-override",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libbase",
+        "libutils",
+    ],
+    sanitize: {
+        address: true,
+        undefined: true,
+        all_undefined: true,
+        fuzzer: true,
+        cfi: true,
+        integer_overflow: true,
+        scs: true,
+    },
+    strip: {
+        keep_symbols_and_debug_frame: true,
+    },
+}
+
+cc_library_static {
+    name: "libnlinterceptor",
+    defaults: ["nlinterceptor@defaults"],
+    vendor_available: true,
+    shared_libs: [
+        "android.hardware.net.nlinterceptor-V1-ndk",
+        "libbinder_ndk",
+    ],
+    srcs: [
+        "libnlinterceptor.cpp",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/wifi/netlinkinterceptor/libnlinterceptor/include/libnlinterceptor/libnlinterceptor.h b/wifi/netlinkinterceptor/libnlinterceptor/include/libnlinterceptor/libnlinterceptor.h
new file mode 100644
index 0000000..ac8653e
--- /dev/null
+++ b/wifi/netlinkinterceptor/libnlinterceptor/include/libnlinterceptor/libnlinterceptor.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+
+#include <aidl/android/hardware/net/nlinterceptor/InterceptedSocket.h>
+#include <android-base/unique_fd.h>
+#include <linux/netlink.h>
+
+#include <optional>
+#include <string>
+
+namespace android::nlinterceptor {
+
+/**
+ * Wrapper structure to uniquely identifies a socket that Netlink Interceptor
+ * has allocated for us.
+ */
+struct InterceptedSocket {
+    uint32_t nlFamily;
+    uint32_t portId;
+
+    InterceptedSocket(
+        ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket sock);
+    InterceptedSocket(uint32_t nlFamily, uint32_t portId);
+
+    bool operator<(const InterceptedSocket& other) const;
+    operator sockaddr_nl() const;
+    operator ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket()
+        const;
+};
+
+/**
+ * Output stream operator for InterceptedSocket
+ */
+std::ostream& operator<<(std::ostream& os, const InterceptedSocket& sock);
+
+/**
+ * Checks if an instance Netlink Interceptor exists.
+ *
+ * \return true if supported, false if not.
+ */
+bool isEnabled();
+
+/**
+ * Asks Netlink Interceptor to allocate a socket to which we can send Netlink
+ * traffic.
+ *
+ * \param clientSocket - File descriptor for the client's Netlink socket.
+ * \param clientName - Human readable name of the client application.
+ * \return Identifier for the socket created by Netlink Interceptor, nullopt on
+ * error.
+ */
+std::optional<InterceptedSocket> createSocket(base::borrowed_fd clientSocket,
+                                              const std::string& clientName);
+
+/**
+ * Asks Netlink Interceptor to close a socket that it created for us previously,
+ * if it exists.
+ *
+ * \param sock - Identifier for the socket created by Netlink Interceptor.
+ */
+void closeSocket(const InterceptedSocket& sock);
+
+/**
+ * Asks Netlink Interceptor to subscribe a socket that it created for us
+ * previously to a specified multicast group.
+ *
+ * \param sock - Identifier for the socket created by Netlink Interceptor.
+ * \param group - A single Netlink multicast group for which we would like to
+ * receive events.
+ * \return true for success, false if something went wrong.
+ */
+bool subscribe(const InterceptedSocket& sock, uint32_t group);
+
+/**
+ * Asks Netlink Interceptor to unsubscribe a socket that it created for us
+ * previously from a specified multicast group.
+ *
+ * \param sock - Identifier for the socket created by Netlink Interceptor.
+ * \param group - A single Netlink multicast group for which we no longer wish
+ * to receive events.
+ * \return true for success, false if something went wrong.
+ */
+bool unsubscribe(const InterceptedSocket& sock, uint32_t group);
+}  // namespace android::nlinterceptor
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// C wrappers for libnlinterceptor
+struct android_nlinterceptor_InterceptedSocket {
+    uint32_t nlFamily;
+    uint32_t portId;
+};
+
+bool android_nlinterceptor_isEnabled();
+
+bool android_nlinterceptor_createSocket(
+    int clientSocketFd, const char* clientName,
+    struct android_nlinterceptor_InterceptedSocket* interceptedSocket);
+
+void android_nlinterceptor_closeSocket(
+    const struct android_nlinterceptor_InterceptedSocket* sock);
+
+bool android_nlinterceptor_subscribe(
+    const struct android_nlinterceptor_InterceptedSocket* sock, uint32_t group);
+
+bool android_nlinterceptor_unsubscribe(
+    const struct android_nlinterceptor_InterceptedSocket* sock, uint32_t group);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/wifi/netlinkinterceptor/libnlinterceptor/libnlinterceptor.cpp b/wifi/netlinkinterceptor/libnlinterceptor/libnlinterceptor.cpp
new file mode 100644
index 0000000..575f900
--- /dev/null
+++ b/wifi/netlinkinterceptor/libnlinterceptor/libnlinterceptor.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/net/nlinterceptor/IInterceptor.h>
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android/binder_manager.h>
+#include <libnlinterceptor/libnlinterceptor.h>
+#include <linux/netlink.h>
+
+#include <mutex>
+
+namespace android::nlinterceptor {
+using namespace std::string_literals;
+using namespace ::aidl::android::hardware::net::nlinterceptor;
+using base::borrowed_fd;
+using AidlInterceptedSocket =
+    ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket;
+
+static const auto kServiceName = IInterceptor::descriptor + "/default"s;
+
+InterceptedSocket::InterceptedSocket(
+    ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket sock)
+    : nlFamily(sock.nlFamily), portId(sock.portId) {}
+
+InterceptedSocket::InterceptedSocket(uint32_t nlFamily, uint32_t portId)
+    : nlFamily(nlFamily), portId(portId) {}
+
+std::ostream& operator<<(std::ostream& os, const InterceptedSocket& sock) {
+    return os << "family: " << sock.nlFamily << ", portId: " << sock.portId;
+}
+
+bool InterceptedSocket::operator<(const InterceptedSocket& other) const {
+    if (nlFamily != other.nlFamily) {
+        return nlFamily < other.nlFamily;
+    }
+    return portId < other.portId;
+}
+
+InterceptedSocket::operator sockaddr_nl() const {
+    return {
+        .nl_family = AF_NETLINK,
+        .nl_pad = 0,
+        .nl_pid = portId,
+        .nl_groups = 0,
+    };
+}
+
+InterceptedSocket::operator AidlInterceptedSocket() const {
+    return {
+        .nlFamily = static_cast<int32_t>(nlFamily),
+        .portId = static_cast<int32_t>(portId),
+    };
+}
+
+bool isEnabled() {
+    static std::mutex supportedMutex;
+    static std::optional<bool> interceptorSupported;
+    // Avoid querying service manager when we can cache the result.
+    if (interceptorSupported.has_value()) return *interceptorSupported;
+    std::lock_guard lock(supportedMutex);
+    if (interceptorSupported.has_value()) return *interceptorSupported;
+
+    if (!AServiceManager_isDeclared(kServiceName.c_str())) {
+        interceptorSupported = false;
+        return false;
+    }
+    interceptorSupported = true;
+    return true;
+}
+
+static IInterceptor& getInstance() {
+    static std::mutex instanceMutex;
+    static std::shared_ptr<IInterceptor> interceptorInstance;
+    CHECK(isEnabled()) << "Can't getInstance! Interceptor not supported!";
+    // Don't overwrite the pointer once we've acquired it.
+    if (interceptorInstance != nullptr) return *interceptorInstance;
+    std::lock_guard lock(instanceMutex);
+    if (interceptorInstance != nullptr) return *interceptorInstance;
+    interceptorInstance = IInterceptor::fromBinder(
+        ndk::SpAIBinder(AServiceManager_waitForService(kServiceName.c_str())));
+    CHECK(interceptorInstance != nullptr)
+        << "Failed to get Netlink Interceptor service!";
+    return *interceptorInstance;
+}
+
+std::optional<InterceptedSocket> createSocket(borrowed_fd clientSocket,
+                                              const std::string& clientName) {
+    sockaddr_nl nladdr = {};
+    socklen_t nlsize = sizeof(nladdr);
+    if (getsockname(clientSocket.get(), reinterpret_cast<sockaddr*>(&nladdr),
+                    &nlsize) < 0) {
+        PLOG(ERROR) << "Failed to get pid of fd passed by " << clientName;
+        return std::nullopt;
+    }
+
+    ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket
+        interceptedSocket;
+    auto aidlStatus = getInstance().createSocket(
+        nladdr.nl_family, nladdr.nl_pid, clientName, &interceptedSocket);
+    if (!aidlStatus.isOk()) {
+        return std::nullopt;
+    }
+
+    return InterceptedSocket{nladdr.nl_family,
+                             uint32_t(interceptedSocket.portId)};
+}
+
+void closeSocket(const InterceptedSocket& sock) {
+    auto aidlStatus = getInstance().closeSocket(sock);
+    if (!aidlStatus.isOk()) {
+        LOG(ERROR) << "Failed to close socket with pid = " << sock.portId;
+    }
+}
+
+bool subscribe(const InterceptedSocket& sock, uint32_t group) {
+    auto aidlStatus = getInstance().subscribeGroup(sock, group);
+    return aidlStatus.isOk();
+}
+
+bool unsubscribe(const InterceptedSocket& sock, uint32_t group) {
+    auto aidlStatus = getInstance().unsubscribeGroup(sock, group);
+    return aidlStatus.isOk();
+}
+
+extern "C" bool android_nlinterceptor_isEnabled() { return isEnabled(); }
+
+extern "C" bool android_nlinterceptor_createSocket(
+    int clientSocketFd, const char* clientName,
+    android_nlinterceptor_InterceptedSocket* interceptedSocket) {
+    if (!clientName || clientSocketFd <= 0) return false;
+    const auto maybeSocket =
+        createSocket(borrowed_fd(clientSocketFd), clientName);
+    if (!maybeSocket) return false;
+    *interceptedSocket = {.nlFamily = maybeSocket->nlFamily,
+                          .portId = maybeSocket->portId};
+    return true;
+}
+
+extern "C" void android_nlinterceptor_closeSocket(
+    const android_nlinterceptor_InterceptedSocket* sock) {
+    if (!sock) {
+        LOG(ERROR) << "Can't close socket identified by a null pointer!";
+        return;
+    }
+    closeSocket({sock->nlFamily, sock->portId});
+}
+
+extern "C" bool android_nlinterceptor_subscribe(
+    const android_nlinterceptor_InterceptedSocket* sock, uint32_t group) {
+    if (!sock) return false;
+    return subscribe({sock->nlFamily, sock->portId}, group);
+}
+
+extern "C" bool android_nlinterceptor_unsubscribe(
+    const android_nlinterceptor_InterceptedSocket* sock, uint32_t group) {
+    if (!sock) return false;
+    return unsubscribe({sock->nlFamily, sock->portId}, group);
+}
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/vts/OWNERS b/wifi/netlinkinterceptor/vts/OWNERS
new file mode 100644
index 0000000..b738dac
--- /dev/null
+++ b/wifi/netlinkinterceptor/vts/OWNERS
@@ -0,0 +1,2 @@
+chrisweir@google.com
+twasilczyk@google.com
diff --git a/wifi/netlinkinterceptor/vts/functional/Android.bp b/wifi/netlinkinterceptor/vts/functional/Android.bp
new file mode 100644
index 0000000..33284e8
--- /dev/null
+++ b/wifi/netlinkinterceptor/vts/functional/Android.bp
@@ -0,0 +1,51 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // 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: "VtsHalNetlinkInterceptorV1_0Test",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    cpp_std: "experimental",
+    srcs: [
+        "interceptor_aidl_test.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.net.nlinterceptor-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "libgmock",
+        "android.hardware.automotive.can@libnetdevice",
+        "libnl++",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    disable_framework: true,
+}
diff --git a/wifi/netlinkinterceptor/vts/functional/interceptor_aidl_test.cpp b/wifi/netlinkinterceptor/vts/functional/interceptor_aidl_test.cpp
new file mode 100644
index 0000000..b26d8ec
--- /dev/null
+++ b/wifi/netlinkinterceptor/vts/functional/interceptor_aidl_test.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/net/nlinterceptor/IInterceptor.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+#include <libnetdevice/libnetdevice.h>
+#include <libnl++/MessageFactory.h>
+#include <libnl++/Socket.h>
+#include <libnl++/printer.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <chrono>
+#include <thread>
+
+using aidl::android::hardware::net::nlinterceptor::IInterceptor;
+using AidlInterceptedSocket =
+    ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket;
+using namespace std::chrono_literals;
+using namespace std::string_literals;
+
+class InterceptorAidlTest : public ::testing::TestWithParam<std::string> {
+   public:
+    virtual void SetUp() override {
+        android::base::SetDefaultTag("InterceptorAidlTest");
+        android::base::SetMinimumLogSeverity(android::base::VERBOSE);
+        const auto instance = IInterceptor::descriptor + "/default"s;
+        mNlInterceptorService = IInterceptor::fromBinder(
+            ndk::SpAIBinder(AServiceManager_getService(instance.c_str())));
+
+        ASSERT_NE(mNlInterceptorService, nullptr);
+        mSocket = std::make_unique<android::nl::Socket>(NETLINK_ROUTE);
+        ASSERT_TRUE(mSocket->getPid().has_value());
+
+        // If the test broke last run, clean up our mess, don't worry about "no
+        // such device".
+        if (android::netdevice::del(mTestIfaceName)) {
+            LOG(WARNING) << "Test interface wasn't cleaned up on previous run!";
+        }
+    }
+
+    void multicastReceiver();
+
+    std::shared_ptr<IInterceptor> mNlInterceptorService;
+    std::unique_ptr<android::nl::Socket> mSocket;
+    bool mRunning;
+    bool mGotMulticast;
+    const std::string mTestIfaceName = "interceptorvts0";
+};
+
+TEST_P(InterceptorAidlTest, createSocketTest) {
+    // Ask IInterceptor for a socket.
+    AidlInterceptedSocket interceptedSocket;
+    auto aidlStatus = mNlInterceptorService->createSocket(
+        NETLINK_ROUTE, *(mSocket->getPid()), "createSocketTest",
+        &interceptedSocket);
+    ASSERT_TRUE(aidlStatus.isOk());
+    ASSERT_NE(interceptedSocket.portId, 0);
+    uint32_t interceptorPid = interceptedSocket.portId;
+
+    // Ask the kernel to tell us what interfaces are available.
+    android::nl::MessageFactory<rtgenmsg> req(RTM_GETLINK,
+                                              NLM_F_REQUEST | NLM_F_DUMP);
+    req->rtgen_family = AF_PACKET;
+    sockaddr_nl sa = {.nl_family = AF_NETLINK,
+                      .nl_pad = 0,
+                      .nl_pid = interceptorPid,
+                      .nl_groups = 0};
+    EXPECT_TRUE(mSocket->send(req, sa));
+
+    // We'll likely get back several messages, as indicated by the MULTI flag.
+    unsigned received = 0;
+    for (const auto msg : *mSocket) {
+        ASSERT_NE(msg->nlmsg_type, NLMSG_ERROR);
+        ++received;
+        break;
+        if (msg->nlmsg_type == NLMSG_DONE) {
+            // TODO(202548749): NLMSG_DONE on NETLINK_ROUTE doesn't work?
+            break;
+        }
+    }
+    ASSERT_GE(received, 1);
+
+    // Close the socket and make sure it's stopped working.
+    aidlStatus = mNlInterceptorService->closeSocket(interceptedSocket);
+    EXPECT_TRUE(aidlStatus.isOk());
+    EXPECT_FALSE(mSocket->send(req, sa));
+}
+
+static bool isSocketReadable(const short revents) {
+    return 0 != (revents & POLLIN);
+}
+
+static bool isSocketBad(const short revents) {
+    return 0 != (revents & (POLLERR | POLLHUP | POLLNVAL));
+}
+
+void InterceptorAidlTest::multicastReceiver() {
+    pollfd fds[] = {
+        mSocket->preparePoll(POLLIN),
+    };
+    while (mRunning) {
+        if (poll(fds, 1, 300) < 0) {
+            PLOG(FATAL) << "poll failed";
+            return;
+        }
+        const auto nlsockEvents = fds[0].revents;
+        ASSERT_FALSE(isSocketBad(nlsockEvents));
+        if (!isSocketReadable(nlsockEvents)) continue;
+
+        const auto [msgMaybe, sa] = mSocket->receiveFrom();
+        ASSERT_TRUE(msgMaybe.has_value());
+        auto msg = *msgMaybe;
+
+        // Multicast messages have 0 for their pid and sequence number.
+        if (msg->nlmsg_pid == 0 && msg->nlmsg_seq == 0) {
+            mGotMulticast = true;
+        }
+    }
+}
+
+TEST_P(InterceptorAidlTest, subscribeGroupTest) {
+    // Ask IInterceptor for a socket.
+    AidlInterceptedSocket interceptedSocket;
+    auto aidlStatus = mNlInterceptorService->createSocket(
+        NETLINK_ROUTE, *(mSocket->getPid()), "subscribeGroupTest",
+        &interceptedSocket);
+    ASSERT_TRUE(aidlStatus.isOk());
+    ASSERT_TRUE(interceptedSocket.portId != 0);
+
+    // Listen for interface up/down events.
+    aidlStatus =
+        mNlInterceptorService->subscribeGroup(interceptedSocket, RTNLGRP_LINK);
+    ASSERT_TRUE(aidlStatus.isOk());
+
+    // Start a thread to receive a multicast
+    mRunning = true;
+    mGotMulticast = false;
+    std::thread successfulReceiver(&InterceptorAidlTest::multicastReceiver,
+                                   this);
+
+    // TODO(201695162): use futures with wait_for instead of a sleep_for().
+    std::this_thread::sleep_for(50ms);
+    // create a network interface and bring it up to trigger a multicast event.
+    ASSERT_TRUE(android::netdevice::add(mTestIfaceName, /*type=*/"dummy"));
+    ASSERT_TRUE(android::netdevice::up(mTestIfaceName));
+    std::this_thread::sleep_for(50ms);
+    EXPECT_TRUE(mGotMulticast);
+    mRunning = false;
+    successfulReceiver.join();
+
+    // Stop listening to interface up/down events.
+    aidlStatus = mNlInterceptorService->unsubscribeGroup(interceptedSocket,
+                                                         RTNLGRP_LINK);
+    ASSERT_TRUE(aidlStatus.isOk());
+
+    // This time, we should hear nothing.
+    mGotMulticast = false;
+    mRunning = true;
+    std::thread unsuccessfulReceiver(&InterceptorAidlTest::multicastReceiver,
+                                     this);
+    std::this_thread::sleep_for(50ms);
+    ASSERT_TRUE(android::netdevice::down(mTestIfaceName));
+    ASSERT_TRUE(android::netdevice::del(mTestIfaceName));
+    std::this_thread::sleep_for(50ms);
+    EXPECT_FALSE(mGotMulticast);
+    mRunning = false;
+    unsuccessfulReceiver.join();
+
+    aidlStatus = mNlInterceptorService->closeSocket(interceptedSocket);
+    EXPECT_TRUE(aidlStatus.isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InterceptorAidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, InterceptorAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IInterceptor::descriptor)),
+                         android::PrintInstanceNameToString);